mirror of
https://github.com/almet/notmyidea.git
synced 2025-04-28 19:42:37 +02:00
11659 lines
No EOL
1.4 MiB
11659 lines
No EOL
1.4 MiB
<?xml version="1.0" encoding="utf-8"?>
|
||
<feed xmlns="http://www.w3.org/2005/Atom"><title>Alexis Métaireau</title><link href="https://blog.notmyidea.org/" rel="alternate"></link><link href="https://blog.notmyidea.org/feeds/.atom.xml" rel="self"></link><id>https://blog.notmyidea.org/</id><updated>2023-11-23T00:00:00+01:00</updated><entry><title>Using pelican to track my worked and volunteer hours</title><link href="https://blog.notmyidea.org/using-pelican-to-track-my-worked-and-volunteer-hours.html" rel="alternate"></link><published>2023-11-23T00:00:00+01:00</published><updated>2023-11-23T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-23:/using-pelican-to-track-my-worked-and-volunteer-hours.html</id><summary type="html"><p>I was tracking my hours in Datasette (<a href="https://blog.notmyidea.org/using-datasette-for-tracking-my-professional-activity.html">article</a> and <a href="https://blog.notmyidea.org/deploying-and-customizing-datasette.html">follow-up</a>), but I wasn&#8217;t really happy with the editing&nbsp;process.</p>
|
||
<p>I&#8217;ve seen <a href="https://larlet.fr/david">David</a> notes, which made me want to do something&nbsp;similar.</p>
|
||
<p>I&#8217;m consigning everything in markdown files and as such, was already keeping track of everything this …</p></summary><content type="html"><p>I was tracking my hours in Datasette (<a href="https://blog.notmyidea.org/using-datasette-for-tracking-my-professional-activity.html">article</a> and <a href="https://blog.notmyidea.org/deploying-and-customizing-datasette.html">follow-up</a>), but I wasn&#8217;t really happy with the editing&nbsp;process.</p>
|
||
<p>I&#8217;ve seen <a href="https://larlet.fr/david">David</a> notes, which made me want to do something&nbsp;similar.</p>
|
||
<p>I&#8217;m consigning everything in markdown files and as such, was already keeping track of everything this way already. Tracking my hours should be simple otherwise I might just oversee it. So I hacked something together with <a href="https://github.com/getpelican/pelican">pelican</a> (the software I wrote for this&nbsp;blog).</p>
|
||
<p><img alt="A graph showing the worked hours and volunteer hours" src="/images/pelican/worklog.png"></p>
|
||
<p>It&#8217;s doing the&nbsp;following:</p>
|
||
<ol>
|
||
<li>Defines a specific format for my worklog&nbsp;entries</li>
|
||
<li>Parses them (using a regexp), does some computation and&nbsp;;</li>
|
||
<li>Uses a specific template to display a graph and progress&nbsp;bar.</li>
|
||
</ol>
|
||
<h2 id="reading-information-from-the-titles">Reading information from the&nbsp;titles</h2>
|
||
<p>I actually took the format I&#8217;ve been already using in my log, and enhanced it a bit.
|
||
Basically, the files look likes this (I&#8217;m writing in&nbsp;french):</p>
|
||
<div class="highlight"><pre><span></span><code>---
|
||
title: My project
|
||
<span class="gu">total_days: 25</span>
|
||
<span class="gu">---</span>
|
||
|
||
<span class="gu">## Mardi 23 Novembre 2023 (9h, 5/5)</span>
|
||
|
||
What I did this day.
|
||
I can include [<span class="nt">links</span>](<span class="na">https://domain.tld</span>) and whatever I want.
|
||
It won&#39;t be processed.
|
||
|
||
<span class="gu">## Lundi 22 Novembre 2023 (8h rémunérées, 2h bénévoles, 4/5)</span>
|
||
|
||
Something else.
|
||
</code></pre></div>
|
||
|
||
<p>Basically, the second titles (h2) are parsed, and should have the following structure:
|
||
<code>{day_of_week} {day} {month} {year} ({worked_hours}(, optional {volunteer_hours}), {fun_rank})</code></p>
|
||
<p>The goal here is to retrieve all of this, so I asked ChatGPT for a regexp and iterated on the result which got&nbsp;me:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">pattern</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
|
||
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;</span>
|
||
<span class="sd"> (\w+)\s+ # Day name</span>
|
||
<span class="sd"> (\d{1,2})\s+ # Day number</span>
|
||
<span class="sd"> ([\wéû]+)\s+ # Month name</span>
|
||
<span class="sd"> (\d{4})\s+ # Year</span>
|
||
<span class="sd"> \(</span>
|
||
<span class="sd"> (\d{1,2})h # Hours (mandatory)</span>
|
||
<span class="sd"> (?:\s+facturées)? # Optionally &#39;facturées&#39;, if not present, assume hours are &#39;facturées&#39;</span>
|
||
<span class="sd"> (?:,\s*(\d{1,2})h\s*bénévoles)? # Optionally &#39;volunteer hours &#39;bénévoles&#39;</span>
|
||
<span class="sd"> ,? # An optional comma</span>
|
||
<span class="sd"> \s* # Optional whitespace</span>
|
||
<span class="sd"> (?:fun\s+)? # Optionally &#39;fun&#39; (text) followed by whitespace</span>
|
||
<span class="sd"> (\d)/5 # Happiness rating (mandatory, always present)</span>
|
||
<span class="sd"> \) # Closing parenthesis</span>
|
||
<span class="sd"> &quot;&quot;&quot;</span><span class="p">,</span>
|
||
<span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span> <span class="o">|</span> <span class="n">re</span><span class="o">.</span><span class="n">UNICODE</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="the-markdown-preprocessor">The markdown&nbsp;preprocessor</h2>
|
||
<p>I&#8217;m already using a custom pelican plugin, which makes it possible to have pelican behave exactly the way I want. For instance, it&#8217;s getting the date from the&nbsp;filesystem.</p>
|
||
<p>I just had to add some features to it. The way I&#8217;m doing this is by <a href="https://docs.getpelican.com/en/3.6.2/plugins.html#how-to-create-a-new-reader">using a custom Markdown reader</a>, on which I add extensions and custom&nbsp;processors.</p>
|
||
<p>In my case, I added a preprocessor which will only run when we are handling the worklog. It makes it possible to change what&#8217;s being read, before the markdown lib actually transforms it to <span class="caps">HTML</span>.</p>
|
||
<p>Here is the code for&nbsp;it:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">WorklogPreprocessor</span><span class="p">(</span><span class="n">Preprocessor</span><span class="p">):</span>
|
||
<span class="n">pattern</span> <span class="o">=</span> <span class="s2">&quot;the regexp we&#39;ve seen earlier&quot;</span>
|
||
|
||
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lines</span><span class="p">):</span>
|
||
<span class="n">new_lines</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;##&quot;</span><span class="p">):</span>
|
||
<span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pattern</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Unable to parse worklog title&quot;</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
|
||
<span class="p">(</span>
|
||
<span class="n">day_of_week</span><span class="p">,</span>
|
||
<span class="n">day</span><span class="p">,</span>
|
||
<span class="n">month</span><span class="p">,</span>
|
||
<span class="n">year</span><span class="p">,</span>
|
||
<span class="n">payed_hours</span><span class="p">,</span>
|
||
<span class="n">volunteer_hours</span><span class="p">,</span>
|
||
<span class="n">happiness</span><span class="p">,</span>
|
||
<span class="p">)</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
|
||
|
||
<span class="n">volunteer_hours</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">volunteer_hours</span><span class="p">)</span> <span class="k">if</span> <span class="n">volunteer_hours</span> <span class="k">else</span> <span class="mi">0</span>
|
||
<span class="n">payed_hours</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">payed_hours</span><span class="p">)</span>
|
||
<span class="n">happiness</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">happiness</span><span class="p">)</span>
|
||
|
||
<span class="n">date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">day</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">month</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">year</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%d</span><span class="s2"> %B %Y&quot;</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="n">date</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&quot;%Y-%m-</span><span class="si">%d</span><span class="s2">&quot;</span><span class="p">)]</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">&quot;payed_hours&quot;</span><span class="p">:</span> <span class="n">payed_hours</span><span class="p">,</span>
|
||
<span class="s2">&quot;volunteer_hours&quot;</span><span class="p">:</span> <span class="n">volunteer_hours</span><span class="p">,</span>
|
||
<span class="s2">&quot;happyness&quot;</span><span class="p">:</span> <span class="n">happiness</span><span class="p">,</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="c1"># Replace the line with just the date</span>
|
||
<span class="n">new_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;## 🗓️ </span><span class="si">{</span><span class="n">day_of_week</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">day</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">month</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">year</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">new_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">new_lines</span>
|
||
</code></pre></div>
|
||
|
||
<p>It does the following when it encounters a h2&nbsp;line:</p>
|
||
<ul>
|
||
<li>try to parse&nbsp;it</li>
|
||
<li>store the data&nbsp;locally</li>
|
||
<li>replace the line with a simpler&nbsp;version</li>
|
||
<li>If if doesn&#8217;t work, error&nbsp;out.</li>
|
||
</ul>
|
||
<p>I&#8217;ve also added some computations on top of it, which makes it possible to display a percentage of completion for the project, if &#8220;payed_hours&#8221; was present in the metadata, and makes it use a specific template (see&nbsp;later).</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">compute_data</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
|
||
<span class="n">done_hours</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="n">item</span><span class="p">[</span><span class="s2">&quot;payed_hours&quot;</span><span class="p">]</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">values</span><span class="p">()])</span>
|
||
|
||
<span class="n">data</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
|
||
<span class="n">data</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span>
|
||
<span class="n">done_hours</span><span class="o">=</span><span class="n">done_hours</span><span class="p">,</span>
|
||
<span class="n">template</span><span class="o">=</span><span class="s2">&quot;worklog&quot;</span><span class="p">,</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="s2">&quot;total_days&quot;</span> <span class="ow">in</span> <span class="n">metadata</span><span class="p">:</span>
|
||
<span class="n">total_hours</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">metadata</span><span class="p">[</span><span class="s2">&quot;total_days&quot;</span><span class="p">])</span> <span class="o">*</span> <span class="mi">7</span>
|
||
<span class="n">data</span><span class="o">.</span><span class="n">update</span><span class="p">(</span>
|
||
<span class="nb">dict</span><span class="p">(</span>
|
||
<span class="n">total_hours</span><span class="o">=</span><span class="n">total_hours</span><span class="p">,</span>
|
||
<span class="n">percentage</span><span class="o">=</span><span class="nb">round</span><span class="p">(</span><span class="n">done_hours</span> <span class="o">/</span> <span class="n">total_hours</span> <span class="o">*</span> <span class="mi">100</span><span class="p">),</span>
|
||
<span class="p">)</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">data</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="plugging-this-with-pelican">Plugging this with&nbsp;pelican</h2>
|
||
<p>Here&#8217;s the code for extending a custom reader, basically adding a pre-processor and adding back its data in the document&nbsp;metadata:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">is_worklog</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="n">source_path</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s2">&quot;pages/worklog&quot;</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">is_worklog</span><span class="p">:</span>
|
||
<span class="n">worklog</span> <span class="o">=</span> <span class="n">WorklogPreprocessor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_md</span><span class="p">)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">_md</span><span class="o">.</span><span class="n">preprocessors</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">worklog</span><span class="p">,</span> <span class="s2">&quot;worklog&quot;</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
|
||
|
||
<span class="c1"># process the markdown, and then</span>
|
||
|
||
<span class="k">if</span> <span class="n">is_worklog</span><span class="p">:</span>
|
||
<span class="n">metadata</span><span class="p">[</span><span class="s2">&quot;worklog&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">worklog</span><span class="o">.</span><span class="n">compute_data</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="adding-a-graph">Adding a&nbsp;graph</h2>
|
||
<p>Okay, everything is parsed, but it&#8217;s not yet displayed on the pages. I&#8217;m using <a href="https://vega.github.io/vega-lite/docs/">vega-lite</a> to display a&nbsp;graph.</p>
|
||
<p>Here is my template for this (stored in <code>template/worklog.html</code>), it&#8217;s doing a stacked bar chart with my&nbsp;data.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kd">const</span><span class="w"> </span><span class="nx">spec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;$schema&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;https://vega.github.io/schema/vega-lite/v5.json&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;width&quot;</span><span class="o">:</span><span class="w"> </span><span class="mf">500</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;height&quot;</span><span class="o">:</span><span class="w"> </span><span class="mf">200</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;data&quot;</span><span class="o">:</span><span class="w"> </span>
|
||
<span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;table&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;values&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">[</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="o">%</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nx">date</span><span class="p">,</span><span class="w"> </span><span class="nx">item</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="nx">page</span><span class="p">.</span><span class="nx">metadata</span><span class="p">.</span><span class="nx">worklog</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">items</span><span class="p">()</span><span class="w"> </span><span class="o">%</span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="s2">&quot;date&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;{{ date }}&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;series&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Rémunéré&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;count&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">item</span><span class="p">[</span><span class="s1">&#39;payed_hours&#39;</span><span class="p">]</span><span class="w"> </span><span class="p">}}},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="s2">&quot;date&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;{{ date }}&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;series&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Bénévole&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;count&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">item</span><span class="p">[</span><span class="s1">&#39;volunteer_hours&#39;</span><span class="p">]</span><span class="w"> </span><span class="p">}}},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="o">%</span><span class="w"> </span><span class="nx">endfor</span><span class="w"> </span><span class="o">%</span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">]</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;mark&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;bar&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;encoding&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;x&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;timeUnit&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="s2">&quot;unit&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;dayofyear&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;step&quot;</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;field&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;date&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;axis&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="s2">&quot;format&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;%d/%m&quot;</span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;title&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Date&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;step&quot;</span><span class="o">:</span><span class="w"> </span><span class="mf">1</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;y&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;aggregate&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;sum&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;field&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;count&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;title&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Heures&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;color&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;field&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;series&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;scale&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;domain&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;Bénévole&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;Rémunéré&quot;</span><span class="p">],</span>
|
||
<span class="w"> </span><span class="s2">&quot;range&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;#e7ba52&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;#1f77b4&quot;</span><span class="p">]</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;title&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Type d&#39;heures&quot;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">};</span>
|
||
|
||
<span class="w"> </span><span class="nx">vegaEmbed</span><span class="p">(</span><span class="s2">&quot;#vis&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">spec</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="c1">// result.view provides access to the Vega View API</span>
|
||
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">result</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">))</span>
|
||
<span class="w"> </span><span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">);</span>
|
||
</code></pre></div>
|
||
|
||
<p>I&#8217;ve also added a small progress bar, made with unicode, which looks like&nbsp;this.</p>
|
||
<div class="highlight"><pre><span></span><code>▓▓░░░░░░░░ 29% (51h / 175 prévues)
|
||
</code></pre></div>
|
||
|
||
<p>Here is the code for&nbsp;it:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="cp">{%</span> <span class="k">if</span> <span class="s2">&quot;total_days&quot;</span> <span class="k">in</span> <span class="nv">page.metadata.keys</span><span class="o">()</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">percentage</span> <span class="o">=</span> <span class="nv">page.metadata.worklog</span><span class="o">[</span><span class="s1">&#39;percentage&#39;</span><span class="o">]</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">total_blocks</span> <span class="o">=</span> <span class="m">10</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">percentage_value</span> <span class="o">=</span> <span class="o">(</span><span class="nv">percentage</span> <span class="o">/</span> <span class="m">100.0</span><span class="o">)</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">full_blocks</span> <span class="o">=</span> <span class="o">((</span><span class="nv">percentage_value</span> <span class="o">*</span> <span class="nv">total_blocks</span><span class="o">)</span> <span class="o">|</span> <span class="nf">round</span><span class="o">(</span><span class="m">0</span><span class="o">,</span> <span class="s1">&#39;floor&#39;</span><span class="o">)</span> <span class="o">)</span> <span class="o">|</span> <span class="nf">int</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">empty_blocks</span> <span class="o">=</span> <span class="nv">total_blocks</span> <span class="o">-</span> <span class="nv">full_blocks</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="nt">&lt;div</span><span class="w"> </span><span class="na">class=</span><span class="s">&quot;progressbar&quot;</span><span class="nt">&gt;</span>
|
||
<span class="w"> </span><span class="c">{# Display full blocks #}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">for</span> <span class="nv">i</span> <span class="k">in</span> <span class="nv">range</span><span class="o">(</span><span class="nv">full_blocks</span><span class="o">)</span> <span class="cp">%}</span>▓<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="c">{# Display empty blocks #}</span>
|
||
<span class="w"> </span><span class="cp">{%</span> <span class="k">for</span> <span class="nv">i</span> <span class="k">in</span> <span class="nv">range</span><span class="o">(</span><span class="nv">empty_blocks</span><span class="o">)</span> <span class="cp">%}</span>░<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
|
||
<span class="w"> </span><span class="cp">{{</span> <span class="nv">percentage</span> <span class="cp">}}</span>%<span class="w"> </span>(<span class="cp">{{</span> <span class="nv">page.metadata.worklog</span><span class="o">[</span><span class="s1">&#39;done_hours&#39;</span><span class="o">]</span> <span class="cp">}}</span>h<span class="w"> </span>/<span class="w"> </span><span class="cp">{{</span> <span class="nv">page.metadata.worklog</span><span class="o">[</span><span class="s1">&#39;total_hours&#39;</span><span class="o">]</span> <span class="cp">}}</span><span class="w"> </span>prévues)
|
||
<span class="w"> </span><span class="nt">&lt;/div&gt;</span>
|
||
</code></pre></div></content><category term="code"></category><category term="Pelican"></category><category term="Work"></category><category term="Vega"></category><category term="Markdown"></category></entry><entry><title>Adding Real-Time Collaboration to uMap, second week</title><link href="https://blog.notmyidea.org/adding-real-time-collaboration-to-umap-second-week.html" rel="alternate"></link><published>2023-11-21T00:00:00+01:00</published><updated>2023-11-21T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-21:/adding-real-time-collaboration-to-umap-second-week.html</id><summary type="html"><p>I continued working on <a href="https://github.com/umap-project/umap/">uMap</a>, an open-source map-making tool to create and share customizable maps, based on Open Street Map&nbsp;data.</p>
|
||
<p>Here is a summary of what I&nbsp;did:</p>
|
||
<ul>
|
||
<li>I reviewed, rebased and made some minor changes to <a href="https://github.com/umap-project/umap/pull/772">a pull request which makes it possible to merge geojson features together …</a></li></ul></summary><content type="html"><p>I continued working on <a href="https://github.com/umap-project/umap/">uMap</a>, an open-source map-making tool to create and share customizable maps, based on Open Street Map&nbsp;data.</p>
|
||
<p>Here is a summary of what I&nbsp;did:</p>
|
||
<ul>
|
||
<li>I reviewed, rebased and made some minor changes to <a href="https://github.com/umap-project/umap/pull/772">a pull request which makes it possible to merge geojson features together</a>&nbsp;;</li>
|
||
<li>I&#8217;ve explored around the idea of using SQLite inside the browser, for two reasons : it could make it possible to use the <a href="https://www.gaia-gis.it/fossil/libspatialite/index">Spatialite</a> extension, and it might help us to implement a <span class="caps">CRDT</span> with <a href="https://github.com/vlcn-io/cr-sqlite">cr-sqlite</a>&nbsp;;</li>
|
||
<li>I learned a lot about the <span class="caps">SIG</span> field. This is a wide ecosystem with lots of moving parts, which I understand a bit better&nbsp;now.</li>
|
||
</ul>
|
||
<h2 id="the-optimistic-merge-approach">The optimistic-merge&nbsp;approach</h2>
|
||
<p>There were an open pull request implementing an &#8220;optimistic merge&#8221;. We spent some time together with Yohan to understand what the pull request is doing, discuss it and made a few&nbsp;changes.</p>
|
||
<p>Here&#8217;s the logic of the&nbsp;changes:</p>
|
||
<ol>
|
||
<li>On the server-side, we detect if we have a conflict between the incoming changes and what&#8217;s stored on the server (is the last document save fresher than the <code>IF-UNMODIFIED-SINCE</code> header we get ?)&nbsp;;</li>
|
||
<li>In case of conflict, find back the reference document in the history (let&#8217;s name this the &#8220;local reference&#8221;)&nbsp;;</li>
|
||
<li>Merge the 3 documents together, that is&nbsp;:</li>
|
||
<li>Find what the the incoming changes are, by comparing the incoming doc to the local&nbsp;reference.</li>
|
||
<li>Re-apply the changes on top of the latest&nbsp;doc.</li>
|
||
</ol>
|
||
<p>One could compare this logic to what happens when you do a <code>git rebase</code>. Here is some&nbsp;pseudo-code:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">def</span> <span class="nf">merge_features</span><span class="p">(</span><span class="n">reference</span><span class="p">:</span> <span class="nb">list</span><span class="p">,</span> <span class="n">latest</span><span class="p">:</span> <span class="nb">list</span><span class="p">,</span> <span class="n">incoming</span><span class="p">:</span> <span class="nb">list</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Finds the changes between reference and incoming, and reapplies them on top of latest.&quot;&quot;&quot;</span>
|
||
<span class="k">if</span> <span class="n">latest</span> <span class="o">==</span> <span class="n">incoming</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">latest</span>
|
||
|
||
<span class="n">reference_removed</span><span class="p">,</span> <span class="n">incoming_added</span> <span class="o">=</span> <span class="n">get_difference</span><span class="p">(</span><span class="n">reference</span><span class="p">,</span> <span class="n">incoming</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Ensure that items changed in the reference weren&#39;t also changed in the latest.</span>
|
||
<span class="k">for</span> <span class="n">removed</span> <span class="ow">in</span> <span class="n">reference_removed</span><span class="p">:</span>
|
||
<span class="k">if</span> <span class="n">removed</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">latest</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">ConflictError</span>
|
||
|
||
<span class="n">merged</span> <span class="o">=</span> <span class="n">copy</span><span class="p">(</span><span class="n">latest</span><span class="p">)</span>
|
||
<span class="c1"># Reapply the changes on top of the latest.</span>
|
||
<span class="k">for</span> <span class="n">removed</span> <span class="ow">in</span> <span class="n">reference_removed</span><span class="p">:</span>
|
||
<span class="n">merged</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="n">removed</span><span class="p">)</span>
|
||
|
||
<span class="k">for</span> <span class="n">added</span> <span class="ow">in</span> <span class="n">incoming_added</span><span class="p">:</span>
|
||
<span class="n">merged</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">added</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">merged</span>
|
||
</code></pre></div>
|
||
|
||
<p>The pull request is not ready yet, as I still want to add tests with real data, and enhance the naming, but that&#8217;s a step in the right direction&nbsp;:-)</p>
|
||
<h2 id="using-sqlite-in-the-browser">Using SQLite in the&nbsp;browser</h2>
|
||
<p>At the moment, (almost) everything is stored on the server side as GeoJSON files. They are simple to use, to read and to write, and having them on the storage makes it easy to handle multiple&nbsp;revisions.</p>
|
||
<p>I&#8217;ve been asked to challenge this idea for a moment. What if we were using some other technology to store the data? What would that give us? What would be the&nbsp;challenges?</p>
|
||
<p>I went with SQLite, just to see what this would&nbsp;mean.</p>
|
||
<ul>
|
||
<li>SQLite is originally not made to work on a web browser, but thanks to Web Assembly, it&#8217;s possible to use it. It&#8217;s not <strong>that</strong> big, but the library weights&nbsp;2Mb.</li>
|
||
<li>With projects such as <a href="https://github.com/vlcn-io/cr-sqlite"><span class="caps">CR</span>-SQLite</a>, you get a way to add CRDTs on top of SQLite databases. Meaning that the clients could send their changes to other clients or to the server, and that it would be easy to integrate&nbsp;;</li>
|
||
<li>The clients could retrieve just some part of the data to the server (e.g. by specifying a bounding box), which gives it the possibility to not load everything in memory if that&#8217;s not&nbsp;needed.</li>
|
||
</ul>
|
||
<p>I wanted to see how it would work, and what would be the challenges around this technology. I wrote a small application with it. Turns out writing to a local in-browser SQLite&nbsp;works.</p>
|
||
<p>Here is what it would look&nbsp;like:</p>
|
||
<ul>
|
||
<li>Each client will get a copy of the database, alongside a version&nbsp;;</li>
|
||
<li>When clients send changes, you can just send the data since the last version&nbsp;;</li>
|
||
<li>Databases can be merged without loosing data, the operations done in <span class="caps">SQL</span> will trigger writes to a specific table, which will be used as a <span class="caps">CRDT</span>.</li>
|
||
</ul>
|
||
<p>I&#8217;m not sure SQLite by itself is useful here. It sure is fun, but I don&#8217;t see what we get in comparison with a more classical <span class="caps">CRDT</span> approach, except complexity. The technology is still quite young and rough to the edges, and uses Rust and WebASM, which are still strange beasts to&nbsp;me. </p>
|
||
<h2 id="related-projects-in-the-sig-field">Related projects in the <span class="caps">SIG</span>&nbsp;field</h2>
|
||
<p>Here are some interesting projects I&#8217;ve found this week&nbsp;:</p>
|
||
<ul>
|
||
<li><a href="https://allartk.github.io/leaflet.offline/">Leaflet.offline</a> allows to store the tiles offline&nbsp;;</li>
|
||
<li><a href="https://github.com/mapbox/geojson-vt">geojson-vt</a> uses the concept of &#8220;vector tiles&#8221; I didn&#8217;t know about. Tiles can return binary or vectorial data, which can be useful to just get the data in one specific bounding box This allows us for instance to store GeoJSON in vector&nbsp;tiles.</li>
|
||
<li><a href="https://github.com/mapbox/mapbox-gl-js">mapbox-gl-js</a> makes it possible to render <span class="caps">SIG</span>-related data using WebGL (no connection with&nbsp;Leaflet)</li>
|
||
<li><a href="https://github.com/BenjaminVadant/leaflet-ugeojson">leaflet-ugeojson</a> and <a href="https://github.com/jieter/Leaflet.Sync">leaflet.Sync</a> allows multiple people to share the same view on a&nbsp;map.</li>
|
||
</ul>
|
||
<p>Two libraries seems useful for&nbsp;us:</p>
|
||
<ul>
|
||
<li><a href="https://github.com/ATran31/Leaflet-GeoSSE">Leaflet-GeoSSE</a> makes it possible to use <span class="caps">SSE</span> (Server Sent Events) to update local data. It uses events (create, update, delete) and keys in the GeoJSON&nbsp;features..</li>
|
||
<li><a href="https://github.com/perliedman/leaflet-realtime">Leaflet Realtime</a> does something a bit similar, but doesn&#8217;t take care of the transport. It&#8217;s meant to be used to track remote elements (a <span class="caps">GPS</span> tracker for&nbsp;instance)</li>
|
||
</ul>
|
||
<p>I&#8217;m noting&nbsp;that:</p>
|
||
<ul>
|
||
<li>In the two libraries, unique identifiers are added to the <code>features</code> to allow for&nbsp;updates.</li>
|
||
<li>None of these libraries makes it possible to track local changes. That&#8217;s what&#8217;s left to&nbsp;find.</li>
|
||
</ul>
|
||
<h2 id="how-to-transport-the-data">How to transport the&nbsp;data?</h2>
|
||
<p>One of the related subjects is transportation of the data between the client and the server. When we&#8217;ll get the local changes, we&#8217;ll need to find a way to send this data to the other clients, and ultimately to the&nbsp;server.</p>
|
||
<p>There are multiple ways to do this, and I spent some time trying to figure out the pros and cons of each approach. Here is a&nbsp;list:</p>
|
||
<ul>
|
||
<li><strong>WebRTC, the <span class="caps">P2P</span> approach</strong>. You let the clients talk to each other. I&#8217;m not sure where the server fits in this scenario. I&#8217;ve yet to figure-out how this works out in real-case scenarii, where you&#8217;re working behind a <span class="caps">NAT</span>, for instance. Also, what&#8217;s the requirement on <span class="caps">STUN</span> / Turn servers,&nbsp;etc. </li>
|
||
<li>Using <strong>WebSockets</strong> seems nice at the first glance, but I&#8217;m concerned about the resources this could take on the server. The requirement we have on &#8220;real-time&#8221; is not that big (e.g. if it&#8217;s not immediate, it&#8217;s&nbsp;okay).</li>
|
||
<li>Using <strong>Server Sent Events</strong> is another way to solve this, it seems lighter on the client and on the server. The server still needs to keep connexion opens, but I&#8217;ve found some proxies which will do that for you, so it would be something to put between the uMap server and the <span class="caps">HTTP</span>&nbsp;server.</li>
|
||
<li><strong>Polling</strong> means less connexion open, but also that the server will need to keep track of the messages the clients have to get. It&#8217;s easily solvable with a Redis queue for&nbsp;instance.</li>
|
||
</ul>
|
||
<p>All of these scenarii are possible, and each of them has pros and cons. I&#8217;ll be working on a document this week to better understand what&#8217;s hidden behind each of these, so we can ultimately make a&nbsp;choice.</p>
|
||
<h3 id="server-sent-events-sse">Server-Sent Events (<span class="caps">SSE</span>)</h3>
|
||
<p>Here are some notes about <span class="caps">SSE</span>. I&#8217;ve learned&nbsp;that:</p>
|
||
<ul>
|
||
<li><span class="caps">SSE</span> makes it so that server connections never ends (so it consumes a&nbsp;process?)</li>
|
||
<li>There is a library in Django for this, named <a href="https://github.com/fanout/django-eventstream">django-eventstream</a></li>
|
||
<li><a href="https://channels.readthedocs.io/en/latest/">Django channels</a> aims at using <span class="caps">ASGI</span> for certain parts of the&nbsp;app.</li>
|
||
<li>You don&#8217;t have to handle all this in Django. It&#8217;s possible to delegate it to <a href="https://github.com/fastly/pushpin">pushpin</a>, a proxy, using <a href="https://github.com/fanout/django-grip">django-grip</a></li>
|
||
</ul>
|
||
<p>It&#8217;s questioning me in terms of infrastructure&nbsp;changes.</p></content><category term="code"></category><category term="Python"></category><category term="CRDT"></category><category term="Sync"></category><category term="uMap"></category></entry><entry><title>2023, Semaine 46</title><link href="https://blog.notmyidea.org/2023-semaine-46.html" rel="alternate"></link><published>2023-11-20T00:00:00+01:00</published><updated>2023-11-20T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-20:/2023-semaine-46.html</id><summary type="html">
|
||
<p>Une semaine de progrès en cartographie et stockage de données. J&#8217;ai senti le besoin de mieux m&#8217;organiser pour améliorer l&#8217;équilibre travail /&nbsp;perso.</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<p><strong><a href="https://github.com/umap-project/umap/">uMap</a></strong></p>
|
||
<p>Je continue mon exploration autour des solutions techniques pour faire de la cartographie temps réelle. J&#8217;ai pris le …</p></summary><content type="html">
|
||
<p>Une semaine de progrès en cartographie et stockage de données. J&#8217;ai senti le besoin de mieux m&#8217;organiser pour améliorer l&#8217;équilibre travail /&nbsp;perso.</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<p><strong><a href="https://github.com/umap-project/umap/">uMap</a></strong></p>
|
||
<p>Je continue mon exploration autour des solutions techniques pour faire de la cartographie temps réelle. J&#8217;ai pris le temps de comprendre différents concepts qui m&#8217;échappaient dans le monde du <span class="caps">SIG</span>. Je comprends maintenant mieux à quoi servent des projets comme <a href="https://docs.protomaps.com/pmtiles/">pmtiles</a> par&nbsp;exemple.</p>
|
||
<p>On a fait de la revue de code avec Yohann sur une manière de faire de la résolution de conflits de manière optimiste, la <span class="caps">PR</span> est presque&nbsp;prête.</p>
|
||
<p>J&#8217;ai exploré ensuite les différentes possibilités de stockage de données, entre autres en me disant que peut-être SQLite était une bonne piste. J&#8217;ai pu faire des tests d&#8217;utilisation de SQLite dans le navigateur, ce qui fonctionne, <a href="https://github.com/vlcn-io/cr-sqlite">et permet de la réplication en utilisant des CRDTs en interne</a>&nbsp;!</p>
|
||
<p><strong><a href="https://chariotte.fr/">Chariotte</a></strong></p>
|
||
<p>J&#8217;ai passé un peu de temps à préparer la migration vers les services d&#8217;AlwaysData. Je me sens rouillé. Tout marche, mais me prends plus de temps que&nbsp;prévu.</p>
|
||
<p><strong>Le groupe, le&nbsp;jeu</strong></p>
|
||
<p>On a bossé une journée avec <a href="https://www.samuelgenin.fr">Sam</a>, et on a découvert <a href="https://github.com/klembot/twinejs">TwineJS</a>, un outil qui permet de travailler sur des histoires à choix multiples. J&#8217;ai fait un outil qui permet d&#8217;importer le format Twee dans notre (futur)&nbsp;jeu.ÒÒ</p>
|
||
<p><strong>Notmyidea</strong></p>
|
||
<p>J&#8217;ai pris du temps cette semaine pour mettre en place une station de travail digne de ce nom. Si je n&#8217;ai pas terminé, je suis content de pouvoir utiliser <a href="https://asahilinux.org/">Asahi Linux</a> sur mon Mac. Certains logiciels (dont Keybase) ne sont pas disponible pour cette architecture logicielle, ce qui m&#8217;a donné du fil à&nbsp;retordre.</p>
|
||
<p>J&#8217;espère bientôt pouvoir migrer complètement dessus, et me faire une session de travail et une session perso comme j&#8217;ai pu faire par le&nbsp;passé.</p>
|
||
<h2 id="des-joies">Des joies&nbsp;🤗</h2>
|
||
<ul>
|
||
<li>Prendre une journée pour faire complètement autre chose. C&#8217;est super de pouvoir m&#8217;organiser comme je&nbsp;l&#8217;entends.</li>
|
||
<li>Recommencer à faire du trombone avec d&#8217;autres personnes. Je ne pensais pas que ça me donnerait autant&nbsp;d&#8217;énergie.</li>
|
||
<li>J&#8217;arrive à mettre des mots sur ce qui s&#8217;est passé pour moi cet été. Je suis content,&nbsp;j&#8217;avance.</li>
|
||
<li>Je prends toujours du plaisir à coder en&nbsp;Elm.</li>
|
||
<li>J&#8217;ai pris beaucoup de plaisir à monter en compétences sur les sujets autour du stockage hors ligne et sur la synchronisation de&nbsp;données.</li>
|
||
<li>Récupérer un lit et meubler ma chambre avec une grande bibliothèque ! C&#8217;est fou comme ça peut faire la&nbsp;différence.</li>
|
||
<li>Avoir un soutien émotionnel extérieur qui ne pèse pas sur mes proches. Je mesure combien ça m&#8217;est précieux et ce que j&#8217;en&nbsp;retire.</li>
|
||
<li>Réussir à expliciter mes besoins auprès de mes&nbsp;proches. </li>
|
||
<li>Une super soirée hors du temps à discuter, se marrer, manger. Qu&#8217;est-ce que ça fait du bien&nbsp;!</li>
|
||
<li>Sentir que l&#8217;approche systémiste m&#8217;aide à mieux analyser certains&nbsp;conflits.</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des peines&nbsp;😬</h2>
|
||
<ul>
|
||
<li>J&#8217;ai culpabilisé à prendre du temps pour apprendre des choses que je ne sais pas, alors même que c&#8217;est ce pour quoi je suis payé. Heureusement que l&#8217;équipe est bienveillante :-) La vie n&#8217;est pas une compétition&nbsp;!</li>
|
||
<li>j&#8217;ai senti les choses flotter à plusieurs reprises lors d&#8217;une visio, alors que j&#8217;aurais aimé plus de cadre. J&#8217;ai envie de me prendre un temps de préparation pour rendre ces moments plus&nbsp;utiles.</li>
|
||
<li>J&#8217;étais désorganisé durant ma semaine de travail. J&#8217;ai fini par couper les sources de distractions (chat, mails). J&#8217;ai envie de commencer cette semaine par une session de planning, on verra ou ça me&nbsp;mène.</li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>🎧 Écouté <a href="https://www.radiofrance.fr/franceculture/podcasts/serie-israel-palestine-les-mots-de-la-guerre">une série de podcasts courts autour du conflit israélo-palestinien</a> sur France Culture. Faire des définitions me parle bien et donne beaucoup du contexte que je&nbsp;manquais.</li>
|
||
<li>🫣 Je suis allé à l&#8217;opéra de Rennes et j&#8217;ai détesté l&#8217;expérience. L&#8217;impression de voir une culture de l&#8217;ancien monde se reproduire en direct.&nbsp;Brrr.</li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>Importing a PostgreSQL dump under a different database name</title><link href="https://blog.notmyidea.org/importing-a-postgresql-dump-under-a-different-database-name.html" rel="alternate"></link><published>2023-11-20T00:00:00+01:00</published><updated>2023-11-20T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-20:/importing-a-postgresql-dump-under-a-different-database-name.html</id><summary type="html"><p>For <a href="https://chariotte.fr">Chariotte</a>, I&#8217;ve had to do an import from one system to the other. I had no control on the export I received. It contained the database name and the ACLs, which I had to change to match the ones on the new&nbsp;system.</p>
|
||
<h2 id="decrypting-the-dump">Decrypting the&nbsp;dump</h2>
|
||
<p>First off …</p></summary><content type="html"><p>For <a href="https://chariotte.fr">Chariotte</a>, I&#8217;ve had to do an import from one system to the other. I had no control on the export I received. It contained the database name and the ACLs, which I had to change to match the ones on the new&nbsp;system.</p>
|
||
<h2 id="decrypting-the-dump">Decrypting the&nbsp;dump</h2>
|
||
<p>First off, the import I received was encrypted, so I had to decrypt it. It took me some time to figure out that both my private <strong>and public</strong> keys needed to be imported to the pgp. Once that was done, I could decrypt&nbsp;with</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Decrypt the file</span>
|
||
gpg<span class="w"> </span>--decrypt<span class="w"> </span>hb_chariotte_prod.pgdump.asc<span class="w"> </span>&gt;<span class="w"> </span>hb_chariotte_prod.pgdump
|
||
|
||
<span class="c1"># Upload it to the server with scp</span>
|
||
scp<span class="w"> </span>hb_chariotte_prod.pgdump<span class="w"> </span>chariotte:.
|
||
</code></pre></div>
|
||
|
||
<h2 id="importing-while-changing-acls-and-database-name">Importing while changing ACLs and database&nbsp;name</h2>
|
||
<p>On the server, here is the command to change the name of the database and the user. The file I received was using the so-called &#8220;custom&#8221; format, which is not editable with a simple editor, so you have to export it to <span class="caps">SQL</span> first, and then edit it before running the actual&nbsp;queries.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Convert to SQL, then replace the table name with the new one, and finally run the SQL statements.</span>
|
||
pg_restore<span class="w"> </span>-C<span class="w"> </span>-f<span class="w"> </span>-<span class="w"> </span>hb_chariotte_prod.pgdump<span class="w"> </span><span class="p">|</span><span class="w"> </span>sed<span class="w"> </span><span class="s1">&#39;s/hb_chariotte_prod/chariotte_temp/g&#39;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>psql<span class="w"> </span>-U<span class="w"> </span>chariotte_temp<span class="w"> </span>-d<span class="w"> </span>chariotte_temp<span class="w"> </span>-h<span class="w"> </span>yourhost
|
||
</code></pre></div></content><category term="code"></category><category term="postgresql"></category><category term="sysadmin"></category></entry><entry><title>Deploying and customizing datasette</title><link href="https://blog.notmyidea.org/deploying-and-customizing-datasette.html" rel="alternate"></link><published>2023-11-12T00:00:00+01:00</published><updated>2023-11-12T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-12:/deploying-and-customizing-datasette.html</id><summary type="html"><p>First, create the venv and install&nbsp;everything</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Create and activate venv</span>
|
||
python3<span class="w"> </span>-m<span class="w"> </span>venv<span class="w"> </span>venv
|
||
<span class="nb">source</span><span class="w"> </span>venv/bin/activate
|
||
|
||
<span class="c1"># Install datasette…</span>
|
||
pip<span class="w"> </span>install<span class="w"> </span>datasette
|
||
|
||
<span class="c1"># … and the plugins</span>
|
||
datasette<span class="w"> </span>install<span class="w"> </span>datasette-render-markdown<span class="w"> </span>datasette-dashboards<span class="w"> </span>datasette-dateutil
|
||
</code></pre></div>
|
||
|
||
<p>I was curious how much all of this was weighting. <span class="caps">30MB</span> seems pretty reasonable to&nbsp;me.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># All of …</span></code></pre></div></summary><content type="html"><p>First, create the venv and install&nbsp;everything</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Create and activate venv</span>
|
||
python3<span class="w"> </span>-m<span class="w"> </span>venv<span class="w"> </span>venv
|
||
<span class="nb">source</span><span class="w"> </span>venv/bin/activate
|
||
|
||
<span class="c1"># Install datasette…</span>
|
||
pip<span class="w"> </span>install<span class="w"> </span>datasette
|
||
|
||
<span class="c1"># … and the plugins</span>
|
||
datasette<span class="w"> </span>install<span class="w"> </span>datasette-render-markdown<span class="w"> </span>datasette-dashboards<span class="w"> </span>datasette-dateutil
|
||
</code></pre></div>
|
||
|
||
<p>I was curious how much all of this was weighting. <span class="caps">30MB</span> seems pretty reasonable to&nbsp;me.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># All of this weights 30Mb</span>
|
||
du<span class="w"> </span>-sh<span class="w"> </span>venv
|
||
30M<span class="w"> </span>venv
|
||
</code></pre></div>
|
||
|
||
<h2 id="adding-authentication">Adding&nbsp;authentication</h2>
|
||
<p>Datasette doesn&#8217;t provide authentication by default, so <a href="https://docs.datasette.io/en/stable/authentication.html">you have to use a plugin for this</a>. I&#8217;ll be using <a href="https://github.com/simonw/datasette-auth-github">Github authentication</a> for now as it seems simple to&nbsp;add:</p>
|
||
<div class="highlight"><pre><span></span><code>pip install datasette-auth-github
|
||
</code></pre></div>
|
||
|
||
<p>I&#8217;ve had to create a new github application and export the variables to my server, and add some configuration to my <code>metadata.yaml</code> file:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nt">allow</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">gh_login</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">almet</span>
|
||
|
||
<span class="nt">plugins</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">datasette-auth-github</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">client_id</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="s">&quot;$env&quot;</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">GITHUB_CLIENT_ID</span>
|
||
<span class="w"> </span><span class="nt">client_secret</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="s">&quot;$env&quot;</span><span class="p p-Indicator">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">GITHUB_CLIENT_SECRET</span>
|
||
</code></pre></div>
|
||
|
||
<p>If that&#8217;s useful to you, here is <a href="https://gitlab.com/almet/timetracker-datasette-deploy">the git repository</a> I&#8217;m deploying to my&nbsp;server.</p>
|
||
<h2 id="using-templates">Using&nbsp;templates</h2>
|
||
<p>Okay, I now want to be able to send an <span class="caps">URL</span> to the people I&#8217;m working with, on which they can see what I&#8217;ve been doing, and what I&#8217;ve been using my time&nbsp;on.</p>
|
||
<p>It was pretty simple to do, and kind of weird to basically do what I&#8217;ve been doing back in the days for my first <span class="caps">PHP</span> applications : put <span class="caps">SQL</span> statements in the templates !&nbsp;heh.</p>
|
||
<p>I&#8217;ve added a template with what I want to do. It has the side-effect of being able to propose a read-only view to a private&nbsp;database.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>{{project}}
|
||
{% for row in sql(&quot;SELECT SUM(CAST(duration AS REAL)) as total_hours FROM journal WHERE project = &#39;&quot; + project + &quot;&#39;;&quot;, database=&quot;db&quot;) %}
|
||
({{ row[&quot;total_hours&quot;] }} heures)
|
||
{% endfor %}
|
||
<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;</span><span class="nt">dl</span><span class="p">&gt;</span>
|
||
{% for row in sql(&quot;select date, CAST(duration AS REAL) as duration, content from journal where project = &#39;&quot; + project + &quot;&#39; order by date DESC&quot;, database=&quot;db&quot;) %}
|
||
<span class="p">&lt;</span><span class="nt">dt</span><span class="p">&gt;</span>{{ row[&quot;date&quot;] }} ({{ row[&quot;duration&quot;] }} heures)<span class="p">&lt;/</span><span class="nt">dt</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;</span><span class="nt">dd</span><span class="p">&gt;</span>{{ render_markdown(row[&quot;content&quot;]) }}<span class="p">&lt;/</span><span class="nt">dd</span><span class="p">&gt;</span>
|
||
{% endfor %}
|
||
<span class="p">&lt;/</span><span class="nt">dl</span><span class="p">&gt;</span>
|
||
</code></pre></div>
|
||
|
||
<p>Which looks like this&nbsp;:</p>
|
||
<p><img alt="Alt text" src="/images/datasette/custom-template.png"></p></content><category term="code"></category><category term="Datasette"></category><category term="Deployment"></category></entry><entry><title>2023, Semaine 45</title><link href="https://blog.notmyidea.org/2023-semaine-45.html" rel="alternate"></link><published>2023-11-11T00:00:00+01:00</published><updated>2023-11-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-11:/2023-semaine-45.html</id><summary type="html">
|
||
<p>Une reprise après deux semaines de pause. Première semaine sur uMap, et beaucoup&nbsp;d&#8217;à-côtés.</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong><a href="https://github.com/umap-project/umap/">uMap</a></strong></dt>
|
||
<dd>J&#8217;ai commencé à travailler sur le projet, que je rejoins pour quelques temps, aux côté de David, Yohan, Aurélie et Sophie. L&#8217;idée est de travailler spécifiquement sur …</dd></dl></summary><content type="html">
|
||
<p>Une reprise après deux semaines de pause. Première semaine sur uMap, et beaucoup&nbsp;d&#8217;à-côtés.</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong><a href="https://github.com/umap-project/umap/">uMap</a></strong></dt>
|
||
<dd>J&#8217;ai commencé à travailler sur le projet, que je rejoins pour quelques temps, aux côté de David, Yohan, Aurélie et Sophie. L&#8217;idée est de travailler spécifiquement sur la collaboration temps réel sur les cartes. J&#8217;ai commencé par lire le code existant, puis par faire un état de l&#8217;art des solutions existantes. Prendre le temps de lire le code, de comparer les différents approches, et de mesurer leurs&nbsp;impacts.</dd>
|
||
<dd>David et Yohan m&#8217;ont proposé de documenter mon travail, j&#8217;ai donc fait <a href="">un premier billet de blog, à paraître</a> (en anglais) sur le&nbsp;sujet.</dd>
|
||
<dt><strong><a href="https://framasoft.frama.io/framaspace/argos/">Argos</a></strong></dt>
|
||
<dd>J&#8217;ai pu échanger sur le code que j&#8217;ai fait avec Matthieu. Ses yeux sont plus avertis, et j&#8217;ai pu avoir des retours intéressants. J&#8217;ai appris entre autres l’existence d&#8217;<a href="https://github.com/mozilla-services/telescope">un projet similaire</a> chez Mozilla, qui recouvre une partie des mêmes usages. Quelques pistes intéressantes la bas. Je n&#8217;ai pas encore pris le temps d&#8217;intégrer les changements, mais j&#8217;aime beaucoup l&#8217;idée de faire des revues de code de ce&nbsp;type.</dd>
|
||
<dt><strong><a href="https://chariotte.fr/">Chariotte</a></strong></dt>
|
||
<dd>J&#8217;ai déployé Chariotte sur l&#8217;infrastructure d&#8217;AlwaysData, qui nous propose <a href="https://www.alwaysdata.com/fr/open-source/">un hébergement gratuit, en tant que projet open source</a>. Tout s&#8217;est passé très simplement et sans&nbsp;accrocs.</dd>
|
||
<dt><strong><a href="https://notmyidea.org/">Notmyidea</a></strong></dt>
|
||
<dd>J&#8217;ai enfin créé la structure pour porter mon activité salariée. Pour le moment je pars sur une auto-entreprise. Le choix se fait après de nombreuses tergiversations. Je suis content d&#8217;écouter mon besoin de limiter mon investissement collectif pour le&nbsp;moment.</dd>
|
||
<dd>J&#8217;ai pris le temps de mettre à jour la page <a href="/projets.html">Projets</a> pour la rendre plus&nbsp;lisible.</dd>
|
||
<dd>J&#8217;ai utilisé Datasette pour faire un suivi des heures que je passe sur chaque projet, et rédigé <a href="/using-datasette-for-tracking-my-professional-activity.html">un article de blog sur le sujet</a>.</dd>
|
||
</dl>
|
||
<h2 id="des-joies">Des joies&nbsp;🤗</h2>
|
||
<ul>
|
||
<li>Ressentir mon envie de reprendre à faire de la technique après deux semaines à faire autre&nbsp;chose.</li>
|
||
<li>Prendre le temps de mesurer la dynamique existante d&#8217;un groupe avant de faire des&nbsp;propositions.</li>
|
||
<li>Réussir ne pas me laisser envahir par des émotions qui ne sont pas les&nbsp;miennes.</li>
|
||
<li>Réunir des amis et amies pour un atelier d&#8217;écriture. Être content d&#8217;entendre les textes des&nbsp;autres.</li>
|
||
<li>Prendre le temps d&#8217;une après-midi pour échanger en toute&nbsp;simplicité.</li>
|
||
<li>Ressentir de la joie en écoutant de la musique. C&#8217;est simple, mais ça marche tellement&nbsp;bien.</li>
|
||
<li>Apprécier une session de brainstorming&nbsp;technique.</li>
|
||
<li>Recroiser des personnes du milieu brassicole sans&nbsp;stresser.</li>
|
||
<li>Faire de la revue de code avec <a href="https://blog.mathieu-leplatre.info/">Matthieu</a>, en profiter pour se donner des&nbsp;nouvelles.</li>
|
||
<li>Avoir du temps seul sans contraintes horaires et me sentir productif à ce moment&nbsp;là.</li>
|
||
<li>Me retrouver dans une voiture sous la pluie battante, entouré d&#8217;amies, en écoutant Clara Ysé à&nbsp;fond.</li>
|
||
<li>Participer à un temps d&#8217;échange de&nbsp;compétences.</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des peines&nbsp;😬</h2>
|
||
<ul>
|
||
<li>Je me suis senti fatigué de passer une après-midi en réunion. Triste de ne pas l&#8217;avoir anticipé alors qu&#8217;on me l&#8217;avait servi sur un&nbsp;plateau.</li>
|
||
<li>Mon rythme s&#8217;améliore, mais cette semaine était trop&nbsp;remplie.</li>
|
||
<li>Peut-être la conséquence : je suis fatigué et en train de tomber&nbsp;malade.</li>
|
||
<li>Je me suis senti parfois anxieux et triste au&nbsp;réveil.</li>
|
||
<li>J&#8217;ai annulé un week-end qui me donnait envie pour éviter de contaminer tout le monde. À la fois frustré et content de prendre soin (de moi et des&nbsp;autres).</li>
|
||
<li>Je me suis senti désorganisé et « flottant » durant ma dernière semaine de&nbsp;pause.</li>
|
||
<li>Ne pas prendre la distance nécessaire avec mes interlocuteurs alors que je me sentais jugé (à tord ou à&nbsp;raison).</li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>🎬 Vu <a href="https://fr.wikipedia.org/wiki/The_Old_Oak">The Old Oak</a>, de Ken Loach. J&#8217;aime beaucoup la finesse du propos, j&#8217;ai fondu en larmes à la fin du film. Ça fait autant de bien que ça questionne sur mes&nbsp;engagements.</li>
|
||
<li>🎬 Vu <a href="https://fr.wikipedia.org/wiki/Victoria_(film,_2016)">Victoria</a> de Justine&nbsp;Triet.</li>
|
||
<li>🎵 Vu en concert <a href="https://fr.wikipedia.org/wiki/Juliette_(chanteuse)">Juliette</a>. J&#8217;ai bien aimé certains textes, ça me donne envie de les écouter plus en&nbsp;détail.</li>
|
||
<li>🎵 Vu en concert <a href="https://fr.wikipedia.org/wiki/French_79">French79</a>, ça fait du bien d&#8217;avoir des vibes positives&nbsp;!</li>
|
||
<li>📖 J&#8217;ai commencé à lire Spin, de Robert Charles&nbsp;Wilson.</li>
|
||
<li>🕸️ Un article d&#8217;Acrimed sur <a href="https://www.acrimed.org/Conflit-israelo-palestinien-calomnies-mediatiques">le traitement du conflit israélo-palestinien dans les médias&nbsp;Français</a></li>
|
||
<li>🎵 J&#8217;ai découvert <a href="https://www.youtube.com/watch?v=YvQAYUb9mu8">Clara Ysé</a>. Quelle puissance&nbsp;!</li>
|
||
<li>🎧 Écouté <a href="https://www.radiofrance.fr/franceculture/podcasts/sous-les-radars/burn-out-militant-mal-ou-symptome-2399524">Burn-out militant, mal ou symptome ?</a> dans l&#8217;émission « sous les radars&nbsp;».</li>
|
||
<li>🎧 Écouté <a href="https://www.radiofrance.fr/franceculture/podcasts/sous-les-radars/logement-la-fin-de-la-france-des-proprietaires-3511615">Logement : la fin de la France des propriétaires&nbsp;?</a> </li>
|
||
</ul>
|
||
<h2 id="technique">Technique</h2>
|
||
<ul>
|
||
<li>J&#8217;ai lu <a href="https://community.openstreetmap.org/t/overturemaps-org-big-businesses-osmf-alternative/6760/7">un thread à propos de Overturemaps sur le forum de <span class="caps">OSM</span></a>, assez éclairant sur ce qu&#8217;est Overture Maps, et la potentielle menace pour <span class="caps">OSM</span>.</li>
|
||
<li>▶︎ Simon Willison à fait <a href="https://www.youtube.com/watch?v=ArnMdc-ICCM&amp;t">une présentation sur les embeddings</a>, comment ils fonctionnent et comment les&nbsp;utiliser. </li>
|
||
<li>▶︎ Une présentation sur <a href="https://www.youtube.com/watch?v=x7drE24geUw">le fonctionnement interne et l&#8217;état de l&#8217;art des CRDTs</a> par Martin&nbsp;Kleppmann</li>
|
||
<li>🕸️ J&#8217;ai découvert <a href="https://freesound.org/">Freesound</a> grace à Sam : une bibliothèque de sons libres de&nbsp;droits.</li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>Adding Real-Time Collaboration to uMap, first week</title><link href="https://blog.notmyidea.org/adding-real-time-collaboration-to-umap-first-week.html" rel="alternate"></link><published>2023-11-11T00:00:00+01:00</published><updated>2023-11-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-11:/adding-real-time-collaboration-to-umap-first-week.html</id><summary type="html"><p>Last week, I&#8217;ve been lucky to start working on <a href="https://github.com/umap-project/umap/">uMap</a>, an open-source map-making tool to create and share customizable maps, based on Open Street Map&nbsp;data.</p>
|
||
<p>My goal is to add real-time collaboration to uMap, but <strong>we first want to be sure to understand the issue correctly</strong>. There are …</p></summary><content type="html"><p>Last week, I&#8217;ve been lucky to start working on <a href="https://github.com/umap-project/umap/">uMap</a>, an open-source map-making tool to create and share customizable maps, based on Open Street Map&nbsp;data.</p>
|
||
<p>My goal is to add real-time collaboration to uMap, but <strong>we first want to be sure to understand the issue correctly</strong>. There are multiple ways to solve this, so one part of the journey is to understand the problem properly (then, we&#8217;ll be able to chose the right path&nbsp;forward).</p>
|
||
<p>Part of the work is documenting it, so expect to see some blog posts around this in the&nbsp;future.</p>
|
||
<h2 id="installation">Installation</h2>
|
||
<p>I&#8217;ve started by installing uMap on my machine, made it work and read the codebase. uMap is written in Python and Django, and using old school Javascript, specifically using the Leaflet library for <span class="caps">SIG</span>-related&nbsp;interface.</p>
|
||
<p>Installing uMap was simple. On a&nbsp;mac:</p>
|
||
<ol>
|
||
<li>Create the venv and activate&nbsp;it</li>
|
||
</ol>
|
||
<div class="highlight"><pre><span></span><code>python3<span class="w"> </span>-m<span class="w"> </span>venv<span class="w"> </span>venv
|
||
<span class="nb">source</span><span class="w"> </span>venv/bin/activate
|
||
pip<span class="w"> </span>install<span class="w"> </span>-e<span class="w"> </span>.
|
||
</code></pre></div>
|
||
|
||
<ol>
|
||
<li>Install the deps : <code>brew install postgis</code> (this will take some time to&nbsp;complete)</li>
|
||
</ol>
|
||
<div class="highlight"><pre><span></span><code>createuser<span class="w"> </span>umap
|
||
createdb<span class="w"> </span>umap<span class="w"> </span>-O<span class="w"> </span>umap
|
||
psql<span class="w"> </span>umap<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;CREATE EXTENSION postgis&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<ol>
|
||
<li>Copy the default config with <code>cp umap/settings/local.py.sample umap.conf</code></li>
|
||
</ol>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Copy the default config to umap.conf</span>
|
||
cp<span class="w"> </span>umap/settings/local.py.sample<span class="w"> </span>umap.conf
|
||
<span class="nb">export</span><span class="w"> </span><span class="nv">UMAP_SETTINGS</span><span class="o">=</span>~/dev/umap/umap.conf
|
||
make<span class="w"> </span>install
|
||
make<span class="w"> </span>installjs
|
||
make<span class="w"> </span>vendors
|
||
umap<span class="w"> </span>migrate
|
||
umap<span class="w"> </span>runserver
|
||
</code></pre></div>
|
||
|
||
<h2 id="and-youre-done">And you&#8217;re&nbsp;done!</h2>
|
||
<p>On Arch Linux, I had to do some changes, but all in all it was&nbsp;simple:</p>
|
||
<div class="highlight"><pre><span></span><code>createuser<span class="w"> </span>umap<span class="w"> </span>-U<span class="w"> </span>postgres
|
||
createdb<span class="w"> </span>umap<span class="w"> </span>-O<span class="w"> </span>umap<span class="w"> </span>-U<span class="w"> </span>postgres
|
||
psql<span class="w"> </span>umap<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;CREATE EXTENSION postgis&quot;</span><span class="w"> </span>-Upostgres
|
||
</code></pre></div>
|
||
|
||
<p>Depending on your installation, you might need to change the <span class="caps">USER</span> that connects the&nbsp;database.</p>
|
||
<p>The configuration could look like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">DATABASES</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="s2">&quot;default&quot;</span><span class="p">:</span> <span class="p">{</span>
|
||
<span class="s2">&quot;ENGINE&quot;</span><span class="p">:</span> <span class="s2">&quot;django.contrib.gis.db.backends.postgis&quot;</span><span class="p">,</span>
|
||
<span class="s2">&quot;NAME&quot;</span><span class="p">:</span> <span class="s2">&quot;umap&quot;</span><span class="p">,</span>
|
||
<span class="s2">&quot;USER&quot;</span><span class="p">:</span> <span class="s2">&quot;postgres&quot;</span><span class="p">,</span>
|
||
<span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="how-its-currently-working">How it&#8217;s currently&nbsp;working</h2>
|
||
<p>With everything working on my machine, I took some time to read the code and understand
|
||
the current code&nbsp;base.</p>
|
||
<p>Here are my findings&nbsp;:</p>
|
||
<ul>
|
||
<li>uMap is currently using a classical client/server architecture where&nbsp;:</li>
|
||
<li>The server is here mainly to handle access rights, store the data and send it over to the&nbsp;clients.</li>
|
||
<li>The actual rendering and modifications of the map are directly done in JavaScript, on the&nbsp;clients.</li>
|
||
</ul>
|
||
<p>The data is split in multiple layers. At the time of writing, concurrent writes to the same layers are not possible, as one edit would potentially overwrite the other. It&#8217;s possible to have concurrent edits on different layers,&nbsp;though.</p>
|
||
<p>When a change occurs, <a href="https://github.com/umap-project/umap/blob/c16a01778b4686a562d97fde1cfd3433777d7590/umap/views.py#L917-L948">each <code>DataLayer</code> is sent by the client to the server</a>.</p>
|
||
<ul>
|
||
<li>The data is updated on the&nbsp;server.</li>
|
||
<li><strong>If the data has been modified by another client</strong>, an <code>HTTP 422 (Unprocessable Entity)</code> status is returned, which makes it possible to detect conflicts. The users are prompted about it, and asked if they want to overwrite the&nbsp;changes.</li>
|
||
<li>The files are stored as geojson files on the server as <code>{datalayer.pk}_{timestamp}.geojson</code>. <a href="https://github.com/umap-project/umap/blob/c16a01778b4686a562d97fde1cfd3433777d7590/umap/models.py#L426-L433">A history of the last changes is preserved</a> (The default settings preserves the last 10&nbsp;revisions).</li>
|
||
<li>The data is stored <a href="https://github.com/umap-project/umap/blob/c16a01778b4686a562d97fde1cfd3433777d7590/umap/static/umap/js/umap.js#L158-L163">in a Leaflet object</a> and <a href="https://github.com/umap-project/umap/blob/c16a01778b4686a562d97fde1cfd3433777d7590/umap/static/umap/js/umap.js#L1095:L1095">backups are made manually</a> (it does not seem that changes are saved&nbsp;automatically).</li>
|
||
</ul>
|
||
<h3 id="data">Data</h3>
|
||
<p>Each layer consists&nbsp;of:</p>
|
||
<ul>
|
||
<li>On one side are the properties (matching the <code>_umap_options</code>), and on the other, the geojson data (the Features&nbsp;key).</li>
|
||
<li>Each feature is composed of three&nbsp;keys:</li>
|
||
<li><strong>geometry</strong>: the actual geo&nbsp;object</li>
|
||
<li><strong>properties</strong>: the data associated with&nbsp;it</li>
|
||
<li><strong>style</strong>: just styling information which goes with it, if&nbsp;any.</li>
|
||
</ul>
|
||
<p><img alt="JSON representation of the umap options" src="/images/umap/umap-options.png">
|
||
<img alt="JSON representation of the umap features" src="/images/umap/umap-features.png"></p>
|
||
<h2 id="real-time-collaboration-the-different-approaches">Real-time collaboration : the different&nbsp;approaches</h2>
|
||
<p>Behind the &#8220;real-time collaboration&#8221; name, we have&nbsp;:</p>
|
||
<ol>
|
||
<li>The <strong>streaming of the changes to the clients</strong>: when you&#8217;re working with other persons on the same map, you can see their edits at the moment they&nbsp;happen.</li>
|
||
<li>The ability to handle <strong>concurrent changes</strong>: some changes can happen on the same data concurrently. In such a case, we need to merge them together and be able&nbsp;to </li>
|
||
<li><strong>Offline editing</strong>: in some cases, one needs to map data but doesn&#8217;t have access to a network. Changes happen on a local device and is then synced with other devices / the server&nbsp;;</li>
|
||
</ol>
|
||
<p><em>Keep in mind these notes are just food for toughs, and that other approaches might be discovered on the&nbsp;way</em></p>
|
||
<p>I&#8217;ve tried to come up with the different approaches I can follow in order to add the collaboration
|
||
features we&nbsp;want.</p>
|
||
<ul>
|
||
<li><strong><span class="caps">JSON</span> Patch and <span class="caps">JSON</span> Merge Patch</strong>: Two specifications by the <span class="caps">IETF</span> which define a format for generating and using diffs on json files. In this scenario, we could send the diffs from the clients to the server, and let it merge&nbsp;everything.</li>
|
||
<li><strong>Using CRDTs</strong>: Conflict-Free Resolution Data Types are one of the other options we have lying around. The technology has been used mainly to solve concurrent editing on text documents (like <a href="https://github.com/ether/etherpad-lite">etherpad-lite</a>), but should work fine on&nbsp;trees.</li>
|
||
</ul>
|
||
<h3 id="json-patch-and-json-merge-patch"><span class="caps">JSON</span> Patch and <span class="caps">JSON</span> Merge&nbsp;Patch</h3>
|
||
<p>I&#8217;ve stumbled on two <span class="caps">IETF</span> specifications for <a href="https://datatracker.ietf.org/doc/html/rfc6902"><span class="caps">JSON</span> Patch</a> and <a href="https://datatracker.ietf.org/doc/html/rfc7396"><span class="caps">JSON</span> Merge Patch</a> which respectively define how <span class="caps">JSON</span> diffs could be defined and&nbsp;applied.</p>
|
||
<p>There are multiple libraries for this, and at least one for <a href="https://github.com/OpenDataServices/json-merge-patch">Python</a>, <a href="https://docs.rs/json-patch/latest/json_patch/">Rust</a> and <a href="https://www.npmjs.com/package/json-merge-patch"><span class="caps">JS</span></a>.</p>
|
||
<p>It&#8217;s even <a href="https://redis.io/commands/json.merge/">supported by the Redis database</a>, which might come handy in case we want to stream the changes with&nbsp;it.</p>
|
||
<p>If you&#8217;re making edits to the map without changing all the data all the time, it&#8217;s possible to generate diffs. For instance, let&#8217;s take this simplified data (it&#8217;s not valid geojson, but it should be enough for&nbsp;testing):</p>
|
||
<p>source.json</p>
|
||
<div class="highlight"><pre><span></span><code><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;features&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
|
||
<span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;key&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;value&quot;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">],</span>
|
||
<span class="w"> </span><span class="nt">&quot;not_changed&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;whatever&quot;</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>And now let&#8217;s add a new object right after the first one&nbsp;:</p>
|
||
<p>destination.geojson</p>
|
||
<div class="highlight"><pre><span></span><code><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;features&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
|
||
<span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;key&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;value&quot;</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;key&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;another-value&quot;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">],</span>
|
||
<span class="w"> </span><span class="nt">&quot;not_changed&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;whatever&quot;</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>If we generate a&nbsp;diff:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">pipx</span> <span class="n">install</span> <span class="n">json</span><span class="o">-</span><span class="n">merge</span><span class="o">-</span><span class="n">patch</span>
|
||
<span class="n">json</span><span class="o">-</span><span class="n">merge</span><span class="o">-</span><span class="n">patch</span> <span class="n">create</span><span class="o">-</span><span class="n">patch</span> <span class="n">source</span><span class="o">.</span><span class="n">json</span> <span class="n">destination</span><span class="o">.</span><span class="n">json</span>
|
||
<span class="p">{</span>
|
||
<span class="s2">&quot;features&quot;</span><span class="p">:</span> <span class="p">[</span>
|
||
<span class="p">{</span>
|
||
<span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;value&quot;</span>
|
||
<span class="p">},</span>
|
||
<span class="p">{</span>
|
||
<span class="s2">&quot;key&quot;</span><span class="p">:</span> <span class="s2">&quot;another-value&quot;</span>
|
||
<span class="p">}</span>
|
||
<span class="p">]</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>Multiple things to note&nbsp;here:</p>
|
||
<ol>
|
||
<li>It&#8217;s a valid <span class="caps">JSON</span>&nbsp;object</li>
|
||
<li>It doesn&#8217;t reproduce the <code>not_changed</code> key</li>
|
||
<li>But… I was expecting to see only the new item to show up. Instead, we are getting two items here, because it&#8217;s replacing the &#8220;features&#8221; key with everything&nbsp;inside.</li>
|
||
</ol>
|
||
<p>This is actually what <a href="https://datatracker.ietf.org/doc/html/rfc6902#section-4.1">the specification defines</a>:</p>
|
||
<blockquote>
|
||
<p>4.1.&nbsp;add</p>
|
||
<p>The &#8220;add&#8221; operation performs one of the following functions,
|
||
depending upon what the target location&nbsp;references:</p>
|
||
<p>o If the target location specifies an array index, a new value is
|
||
inserted into the array at the specified&nbsp;index.</p>
|
||
<p>o If the target location specifies an object member that does not
|
||
already exist, a new member is added to the&nbsp;object</p>
|
||
<p>o <strong>If the target location specifies an object member that does exist,
|
||
that member&#8217;s value is&nbsp;replaced.</strong></p>
|
||
</blockquote>
|
||
<p>It seems too bad for us, as this will happen each time a new feature is added to the feature&nbsp;collection.</p>
|
||
<p>It&#8217;s not working out of the box, but we could probably hack something together by having all features defined by a unique id, and send this to the server. We wouldn&#8217;t be using vanilla <code>geojson</code> files though, but adding some complexity on top of&nbsp;it.</p>
|
||
<p>At this point, I&#8217;ve left this here and went to experiment with the other ideas. After all, the goal here is not (yet) to have something functional, but to clarify how the different options would play&nbsp;off.</p>
|
||
<h3 id="using-crdts">Using&nbsp;CRDTs</h3>
|
||
<p>I&#8217;ve had a look at the two main CRDTs implementation that seem to get traction these days : <a href="https://automerge.org/">Automerge</a> and <a href="https://github.com/yjs/yjs">Yjs</a>.</p>
|
||
<p>I&#8217;ve first tried to make Automerge work with Python, but the <a href="https://github.com/automerge/automerge-py">Automerge-py</a> repository is outdated now and won&#8217;t build. I realized at this point that we might not even need a python&nbsp;implementation: </p>
|
||
<p>In this scenario, the server could just stream the changes from one client to the other, and the <span class="caps">CRDT</span> will guarantee that the structures will be similar on both clients. It&#8217;s handy because it means we won&#8217;t have to implement the <span class="caps">CRDT</span> logic on the server&nbsp;side. </p>
|
||
<p>Let&#8217;s do some JavaScript, then. A simple Leaflet map would look like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">import</span><span class="w"> </span><span class="nx">L</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">&#39;leaflet&#39;</span><span class="p">;</span>
|
||
<span class="k">import</span><span class="w"> </span><span class="s1">&#39;leaflet/dist/leaflet.css&#39;</span><span class="p">;</span>
|
||
|
||
<span class="c1">// Initialize the map and set its view to our chosen geographical coordinates and a zoom level:</span>
|
||
<span class="kd">const</span><span class="w"> </span><span class="nx">map</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">L</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="s1">&#39;map&#39;</span><span class="p">).</span><span class="nx">setView</span><span class="p">([</span><span class="mf">48.1173</span><span class="p">,</span><span class="w"> </span><span class="o">-</span><span class="mf">1.6778</span><span class="p">],</span><span class="w"> </span><span class="mf">13</span><span class="p">);</span>
|
||
|
||
<span class="c1">// Add a tile layer to add to our map, in this case using Open Street Map</span>
|
||
<span class="nx">L</span><span class="p">.</span><span class="nx">tileLayer</span><span class="p">(</span><span class="s1">&#39;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nx">maxZoom</span><span class="o">:</span><span class="w"> </span><span class="kt">19</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="nx">attribution</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;© OpenStreetMap contributors&#39;</span>
|
||
<span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
|
||
|
||
<span class="c1">// Initialize a GeoJSON layer and add it to the map</span>
|
||
<span class="kd">const</span><span class="w"> </span><span class="nx">geojsonFeature</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Feature&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;properties&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Initial Feature&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;popupContent&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;This is where the journey begins!&quot;</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;geometry&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Point&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;coordinates&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="mf">0.09</span><span class="p">,</span><span class="w"> </span><span class="mf">51.505</span><span class="p">]</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">};</span>
|
||
|
||
<span class="kd">const</span><span class="w"> </span><span class="nx">geojsonLayer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">L</span><span class="p">.</span><span class="nx">geoJSON</span><span class="p">(</span><span class="nx">geojsonFeature</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nx">onEachFeature</span><span class="o">:</span><span class="w"> </span><span class="kt">function</span><span class="w"> </span><span class="p">(</span><span class="nx">feature</span><span class="p">,</span><span class="w"> </span><span class="nx">layer</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">popupContent</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nx">layer</span><span class="p">.</span><span class="nx">bindPopup</span><span class="p">(</span><span class="nx">feature</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">popupContent</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">}).</span><span class="nx">addTo</span><span class="p">(</span><span class="nx">map</span><span class="p">);</span>
|
||
|
||
<span class="c1">// Add new features to the map with a click</span>
|
||
<span class="kd">function</span><span class="w"> </span><span class="nx">onMapClick</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">newFeature</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Feature&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;properties&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;New Feature&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;popupContent&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;You clicked the map at &quot;</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">latlng</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="s2">&quot;geometry&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="s2">&quot;type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Point&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;coordinates&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="nx">e</span><span class="p">.</span><span class="nx">latlng</span><span class="p">.</span><span class="nx">lng</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">latlng</span><span class="p">.</span><span class="nx">lat</span><span class="p">]</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">};</span>
|
||
|
||
<span class="w"> </span><span class="c1">// Add the new feature to the geojson layer</span>
|
||
<span class="w"> </span><span class="nx">geojsonLayer</span><span class="p">.</span><span class="nx">addData</span><span class="p">(</span><span class="nx">newFeature</span><span class="p">);</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="nx">map</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;click&#39;</span><span class="p">,</span><span class="w"> </span><span class="nx">onMapClick</span><span class="p">);</span>
|
||
</code></pre></div>
|
||
|
||
<p>Nothing fancy here, just a map which adds markers when you click. Now let&#8217;s add&nbsp;automerge:</p>
|
||
<p>We add a bunch of imports, the goal here will be to sync between tabs of the same browser. Automerge <a href="https://automerge.org/blog/2023/11/06/automerge-repo/">announced an automerge-repo</a> library to help with all the wiring-up, so let&#8217;s try it&nbsp;out!</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">DocHandle</span><span class="p">,</span><span class="w"> </span><span class="nx">isValidAutomergeUrl</span><span class="p">,</span><span class="w"> </span><span class="nx">Repo</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">&#39;@automerge/automerge-repo&#39;</span>
|
||
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">BroadcastChannelNetworkAdapter</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">&#39;@automerge/automerge-repo-network-broadcastchannel&#39;</span>
|
||
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">IndexedDBStorageAdapter</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">&quot;@automerge/automerge-repo-storage-indexeddb&quot;</span>
|
||
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">v4</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">uuidv4</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">&#39;uuid&#39;</span><span class="p">;</span>
|
||
</code></pre></div>
|
||
|
||
<p>These were just import. Don&#8217;t bother too much. The next section does the&nbsp;following:</p>
|
||
<ul>
|
||
<li>Instantiate an &#8220;automerge repo&#8221;, which helps to send the right messages to the other peers if needed&nbsp;;</li>
|
||
<li>Add a mechanism to create and initialize a repository if&nbsp;needed,</li>
|
||
<li>or otherwise look for an existing one, based on a hash passed in the <span class="caps">URI</span>.</li>
|
||
</ul>
|
||
<div class="highlight"><pre><span></span><code><span class="c1">// Add an automerge repository. Sync to </span>
|
||
<span class="kd">const</span><span class="w"> </span><span class="nx">repo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Repo</span><span class="p">({</span>
|
||
<span class="w"> </span><span class="nx">network</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="ow">new</span><span class="w"> </span><span class="nx">BroadcastChannelNetworkAdapter</span><span class="p">()],</span>
|
||
<span class="w"> </span><span class="nx">storage</span><span class="o">:</span><span class="w"> </span><span class="kt">new</span><span class="w"> </span><span class="nx">IndexedDBStorageAdapter</span><span class="p">(),</span>
|
||
<span class="p">});</span>
|
||
|
||
<span class="c1">// Automerge-repo exposes an handle, which is mainly a wrapper around the library internals.</span>
|
||
<span class="kd">let</span><span class="w"> </span><span class="nx">handle</span><span class="o">:</span><span class="w"> </span><span class="kt">DocHandle</span><span class="o">&lt;</span><span class="nx">unknown</span><span class="o">&gt;</span>
|
||
|
||
<span class="kd">const</span><span class="w"> </span><span class="nx">rootDocUrl</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`</span><span class="si">${</span><span class="nb">document</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="si">}</span><span class="sb">`</span>
|
||
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">isValidAutomergeUrl</span><span class="p">(</span><span class="nx">rootDocUrl</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nx">handle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">repo</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">rootDocUrl</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">doc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">handle</span><span class="p">.</span><span class="nx">doc</span><span class="p">();</span>
|
||
|
||
<span class="w"> </span><span class="c1">// Once we&#39;ve found the data in the browser, let&#39;s add the features to the geojson layer.</span>
|
||
<span class="w"> </span><span class="nb">Object</span><span class="p">.</span><span class="nx">values</span><span class="p">(</span><span class="nx">doc</span><span class="p">.</span><span class="nx">features</span><span class="p">).</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">feature</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nx">geojsonLayer</span><span class="p">.</span><span class="nx">addData</span><span class="p">(</span><span class="nx">feature</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="p">});</span>
|
||
|
||
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nx">handle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">repo</span><span class="p">.</span><span class="nx">create</span><span class="p">()</span>
|
||
<span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">handle</span><span class="p">.</span><span class="nx">doc</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="nx">handle</span><span class="p">.</span><span class="nx">change</span><span class="p">(</span><span class="nx">doc</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">doc</span><span class="p">.</span><span class="nx">features</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{});</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>Let&#8217;s change the <code>onMapClick</code> function:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kd">function</span><span class="w"> </span><span class="nx">onMapClick</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">uuid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">uuidv4</span><span class="p">();</span>
|
||
<span class="w"> </span><span class="c1">// ... What was there previously</span>
|
||
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">newFeature</span><span class="p">[</span><span class="s2">&quot;properties&quot;</span><span class="p">][</span><span class="s2">&quot;id&quot;</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">uuid</span><span class="p">;</span>
|
||
|
||
<span class="w"> </span><span class="c1">// Add the new feature to the geojson layer.</span>
|
||
<span class="w"> </span><span class="c1">// Here we use the handle to do the change.</span>
|
||
<span class="w"> </span><span class="nx">handle</span><span class="p">.</span><span class="nx">change</span><span class="p">(</span><span class="nx">doc</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">doc</span><span class="p">.</span><span class="nx">features</span><span class="p">[</span><span class="nx">uuid</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">newFeature</span><span class="p">});</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>And on the other side of the logic, let&#8217;s listen to the&nbsp;changes:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nx">handle</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">&quot;change&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">({</span><span class="nx">doc</span><span class="p">,</span><span class="w"> </span><span class="nx">patches</span><span class="p">})</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="c1">// &quot;patches&quot; is a list of all the changes that happened to the tree.</span>
|
||
<span class="w"> </span><span class="c1">// Because we&#39;re sending JS objects, a lot of patches events are being sent.</span>
|
||
<span class="w"> </span><span class="c1">// </span>
|
||
<span class="w"> </span><span class="c1">// Filter to only keep first-level events (we currently don&#39;t want to reflect</span>
|
||
<span class="w"> </span><span class="c1">// changes down the tree — yet)</span>
|
||
<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;patches&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">patches</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">inserted</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">patches</span><span class="p">.</span><span class="nx">filter</span><span class="p">(({</span><span class="nx">path</span><span class="p">,</span><span class="w"> </span><span class="nx">action</span><span class="p">})</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="nx">path</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">&quot;features&quot;</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">path</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">action</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">&quot;put&quot;</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="p">});</span>
|
||
|
||
<span class="w"> </span><span class="nx">inserted</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(({</span><span class="nx">path</span><span class="p">})</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">uuid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">path</span><span class="p">[</span><span class="mf">1</span><span class="p">];</span>
|
||
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">newFeature</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">doc</span><span class="p">.</span><span class="nx">features</span><span class="p">[</span><span class="nx">uuid</span><span class="p">];</span>
|
||
<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`Adding a new feature at position </span><span class="si">${</span><span class="nx">uuid</span><span class="si">}</span><span class="sb">`</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="nx">geojsonLayer</span><span class="p">.</span><span class="nx">addData</span><span class="p">(</span><span class="nx">newFeature</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="p">});</span>
|
||
<span class="p">});</span>
|
||
</code></pre></div>
|
||
|
||
<p>And… It&#8217;s working, here is a little video capture of two tabs working together&nbsp;:-)</p>
|
||
<video controls preload="none" width="100%"
|
||
poster="https://nuage.b.delire.party/s/kpP9ijfqabmKxnr">
|
||
<source src="https://nuage.b.delire.party/s/kpP9ijfqabmKxnr/download"
|
||
type="video/mp4">
|
||
</video>
|
||
|
||
<p>It&#8217;s very rough, but the point was mainly to see how the library can be used, and what the <span class="caps">API</span> looks like. I&#8217;ve found that&nbsp;:</p>
|
||
<ul>
|
||
<li>The <code>patches</code> object that&#8217;s being sent to the <code>handle.on</code> subscribers is very chatty: it contains all the changes, and I have to filter it to get what I&nbsp;want.</li>
|
||
<li>I was expecting the objects to be sent on one go, but it&#8217;s creating an operation for each change. For instance, setting a new object to a key will result in multiple events, as it will firstly create the object, and the populate&nbsp;it.</li>
|
||
<li>Here I need to keep track of all the edits, but I&#8217;m not sure how that will work out with for instance the offline use-case (or with limited connectivity). That&#8217;s what I&#8217;m going to find out next week, I guess&nbsp;:-)</li>
|
||
<li>The team behind Automerge is very welcoming, and was prompt to answer me when&nbsp;needed.</li>
|
||
<li>There seem to be another <span class="caps">API</span> <code>Automerge.getHistory()</code>, and <code>Automerge.diff()</code> to get a patch between the different docs, which might prove more helpful than getting all the small&nbsp;patches.</li>
|
||
</ul>
|
||
<p>We&#8217;ll figure that out next week, I&nbsp;guess!</p></content><category term="code"></category><category term="Python"></category><category term="CRDT"></category><category term="Sync"></category><category term="uMap"></category></entry><entry><title>Using Datasette for tracking my professional activity</title><link href="https://blog.notmyidea.org/using-datasette-for-tracking-my-professional-activity.html" rel="alternate"></link><published>2023-11-11T00:00:00+01:00</published><updated>2023-11-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-11-11:/using-datasette-for-tracking-my-professional-activity.html</id><summary type="html"><p>I&#8217;ve been following Simon Willison since quite some time, but I&#8217;ve actually never played with his main project <a href="https://datasette.io">Datasette</a>&nbsp;before.</p>
|
||
<p>As I&#8217;m going back into development, I&#8217;m trying to track where my time goes, to be able to find patterns, and just remember how much time …</p></summary><content type="html"><p>I&#8217;ve been following Simon Willison since quite some time, but I&#8217;ve actually never played with his main project <a href="https://datasette.io">Datasette</a>&nbsp;before.</p>
|
||
<p>As I&#8217;m going back into development, I&#8217;m trying to track where my time goes, to be able to find patterns, and just remember how much time I&#8217;ve worked on such and such project. A discussion with <a href="https://thom4.net/">Thomas</a> made me realize it would be nice to track all this in a spreadsheet of some sort, which I was doing until&nbsp;today.</p>
|
||
<p>Spreadsheets are nice, but they don&#8217;t play well with rich content, and doing graphs with them is kind of tricky. So I went ahead and setup everything in&nbsp;Datasette.</p>
|
||
<p>First of all, I&#8217;ve imported my <code>.csv</code> file into a sqlite&nbsp;database: </p>
|
||
<div class="highlight"><pre><span></span><code>sqlite3<span class="w"> </span>-csv<span class="w"> </span>-header<span class="w"> </span>db.sqlite<span class="w"> </span><span class="s2">&quot;.import journal.csv journal&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>Then, I used <a href="https://sqlite-utils.datasette.io/en/stable/">sqlite-utils</a> to do some tidying and changed the columns&nbsp;names:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Rename a column</span>
|
||
sqlite-utils<span class="w"> </span>transform<span class="w"> </span>journal<span class="w"> </span>--rename<span class="w"> </span><span class="s2">&quot;quoi ?&quot;</span><span class="w"> </span>content
|
||
|
||
<span class="c1"># Make everything look similar</span>
|
||
sqlite-utils<span class="w"> </span>update<span class="w"> </span>db.sqlite<span class="w"> </span>journal<span class="w"> </span>project<span class="w"> </span><span class="s1">&#39;value.replace(&quot;Umap&quot;, &quot;uMap&quot;)&#39;</span>
|
||
</code></pre></div>
|
||
|
||
<p>Here is my database&nbsp;schema:</p>
|
||
<div class="highlight"><pre><span></span><code>sqlite-utils<span class="w"> </span>schema<span class="w"> </span>db.sqlite
|
||
CREATE<span class="w"> </span>TABLE<span class="w"> </span><span class="s2">&quot;journal&quot;</span><span class="w"> </span><span class="o">(</span>
|
||
<span class="w"> </span><span class="o">[</span>date<span class="o">]</span><span class="w"> </span>TEXT,
|
||
<span class="w"> </span><span class="o">[</span>project<span class="o">]</span><span class="w"> </span>TEXT,
|
||
<span class="w"> </span><span class="o">[</span>duration<span class="o">]</span><span class="w"> </span>TEXT,
|
||
<span class="w"> </span><span class="o">[</span>where<span class="o">]</span><span class="w"> </span>TEXT,
|
||
<span class="w"> </span><span class="o">[</span>content<span class="o">]</span><span class="w"> </span>TEXT,
|
||
<span class="w"> </span><span class="o">[</span>paid_work<span class="o">]</span><span class="w"> </span>INTEGER
|
||
<span class="o">)</span><span class="p">;</span>
|
||
</code></pre></div>
|
||
|
||
<p>And then installed datasette, with a few plugins, and ran&nbsp;it:</p>
|
||
<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>datasette
|
||
datasette<span class="w"> </span>install<span class="w"> </span>datasette-render-markdown<span class="w"> </span>datasette-write-ui<span class="w"> </span>datasette-dashboards<span class="w"> </span>datasette-dateutil
|
||
</code></pre></div>
|
||
|
||
<p>I then came up with a few <span class="caps">SQL</span> queries which are&nbsp;useful:</p>
|
||
<p>How much I&#8217;ve worked per&nbsp;project:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">sqlite</span><span class="o">-</span><span class="n">utils</span><span class="w"> </span><span class="n">db</span><span class="p">.</span><span class="n">sqlite</span><span class="w"> </span><span class="ss">&quot;SELECT project, SUM(CAST(duration AS REAL)) as total_duration FROM journal GROUP BY project;&quot;</span>
|
||
<span class="p">[</span><span class="err">{</span><span class="ss">&quot;project&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;Argos&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;total_duration&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;project&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;IDLV&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;total_duration&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;project&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;Notmyidea&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;total_duration&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;project&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;Sam&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;total_duration&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;project&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;uMap&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;total_duration&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">]</span>
|
||
</code></pre></div>
|
||
|
||
<p>How much I&#8217;ve worked per week, in total (I&#8217;ve redacted the results for&nbsp;privacy):</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">sqlite</span><span class="o">-</span><span class="n">utils</span><span class="w"> </span><span class="n">db</span><span class="p">.</span><span class="n">sqlite</span><span class="w"> </span><span class="ss">&quot;SELECT strftime(&#39;%Y-W%W&#39;, date) AS week, SUM(CAST(duration AS REAL)) AS hours FROM journal GROUP BY week ORDER BY week;&quot;</span>
|
||
|
||
<span class="p">[</span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W21&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W22&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W23&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W25&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W29&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W37&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W39&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W40&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W41&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W42&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W44&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="err">{</span><span class="ss">&quot;week&quot;</span><span class="p">:</span><span class="w"> </span><span class="ss">&quot;2023-W45&quot;</span><span class="p">,</span><span class="w"> </span><span class="ss">&quot;hours&quot;</span><span class="p">:</span><span class="w"> </span><span class="n">XX</span><span class="err">}</span><span class="p">]</span>
|
||
</code></pre></div>
|
||
|
||
<p>I then created a quick dashboard using <a href="https://github.com/rclement/datasette-dashboards">datasette-dashboard</a>, which looks like&nbsp;this:</p>
|
||
<p><img alt="Capture d'écran du dashboard, heures par semaine" src="/images/datasette/hours-per-week.png">
|
||
<img alt="Capture d'écran du dashboard, heures par projet" src="/images/datasette/hours-per-project.png"></p>
|
||
<p>Using this&nbsp;configuration:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nt">plugins</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">datasette-render-markdown</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">columns</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="s">&quot;content&quot;</span>
|
||
<span class="w"> </span><span class="nt">datasette-dashboards</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">my-dashboard</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Notmyidea</span>
|
||
<span class="w"> </span><span class="nt">filters</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">project</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Projet</span>
|
||
<span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">select</span>
|
||
<span class="w"> </span><span class="nt">db</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">db</span>
|
||
<span class="w"> </span><span class="nt">query</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SELECT DISTINCT project FROM journal WHERE project IS NOT NULL ORDER BY project ASC</span>
|
||
<span class="w"> </span><span class="nt">layout</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">hours-per-project</span><span class="p p-Indicator">]</span>
|
||
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">entries</span><span class="p p-Indicator">]</span>
|
||
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="p p-Indicator">[</span><span class="nv">hours-per-week</span><span class="p p-Indicator">]</span>
|
||
<span class="w"> </span><span class="nt">charts</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">hours-per-project</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Nombre d&#39;heures par projet</span>
|
||
<span class="w"> </span><span class="nt">query</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SELECT project, SUM(CAST(duration AS REAL)) as total FROM journal GROUP BY project;</span>
|
||
<span class="w"> </span><span class="nt">db</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">db</span>
|
||
<span class="w"> </span><span class="nt">library</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">vega-lite</span>
|
||
<span class="w"> </span><span class="nt">display</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">mark</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{</span><span class="nt"> type</span><span class="p">:</span><span class="w"> </span><span class="nv">arc</span><span class="p p-Indicator">,</span><span class="nt"> tooltip</span><span class="p">:</span><span class="w"> </span><span class="nv">true</span><span class="w"> </span><span class="p p-Indicator">}</span>
|
||
<span class="w"> </span><span class="nt">encoding</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">color</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{</span><span class="nt"> field</span><span class="p">:</span><span class="w"> </span><span class="nv">project</span><span class="p p-Indicator">,</span><span class="nt"> type</span><span class="p">:</span><span class="w"> </span><span class="nv">nominal</span><span class="w"> </span><span class="p p-Indicator">}</span>
|
||
<span class="w"> </span><span class="nt">theta</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{</span><span class="nt"> field</span><span class="p">:</span><span class="w"> </span><span class="nv">total</span><span class="p p-Indicator">,</span><span class="nt"> type</span><span class="p">:</span><span class="w"> </span><span class="nv">quantitative</span><span class="w"> </span><span class="p p-Indicator">}</span>
|
||
<span class="w"> </span><span class="nt">hours-per-week</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Heures par semaine</span>
|
||
<span class="w"> </span><span class="nt">query</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SELECT strftime(&#39;%Y-W%W&#39;, date) AS week, SUM(CAST(duration AS REAL)) AS hours FROM journal GROUP BY week ORDER BY week;</span>
|
||
<span class="w"> </span><span class="nt">db</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">db</span>
|
||
<span class="w"> </span><span class="nt">library</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">vega-lite</span>
|
||
<span class="w"> </span><span class="nt">display</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">mark</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{</span><span class="nt"> type</span><span class="p">:</span><span class="w"> </span><span class="nv">bar</span><span class="p p-Indicator">,</span><span class="nt"> tooltip</span><span class="p">:</span><span class="w"> </span><span class="nv">true</span><span class="w"> </span><span class="p p-Indicator">}</span>
|
||
<span class="w"> </span><span class="nt">encoding</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">x</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{</span><span class="nt"> field</span><span class="p">:</span><span class="w"> </span><span class="nv">week</span><span class="p p-Indicator">,</span><span class="nt"> type</span><span class="p">:</span><span class="w"> </span><span class="nv">ordinal</span><span class="p p-Indicator">}</span>
|
||
<span class="w"> </span><span class="nt">y</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{</span><span class="nt"> field</span><span class="p">:</span><span class="w"> </span><span class="nv">hours</span><span class="p p-Indicator">,</span><span class="nt"> type</span><span class="p">:</span><span class="w"> </span><span class="nv">quantitative</span><span class="w"> </span><span class="p p-Indicator">}</span>
|
||
|
||
<span class="w"> </span><span class="nt">entries</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Journal</span>
|
||
<span class="w"> </span><span class="nt">db</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">db</span>
|
||
<span class="w"> </span><span class="nt">query</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SELECT * FROM journal WHERE TRUE [[ AND project = :project ]] ORDER BY date DESC</span>
|
||
<span class="w"> </span><span class="nt">library</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">table</span>
|
||
<span class="w"> </span><span class="nt">display</span><span class="p">:</span>
|
||
</code></pre></div>
|
||
|
||
<p>And ran datasette&nbsp;with:</p>
|
||
<div class="highlight"><pre><span></span><code>datasette<span class="w"> </span>db.sqlite<span class="w"> </span>--root<span class="w"> </span>--metadata<span class="w"> </span>metadata.yaml
|
||
</code></pre></div></content><category term="code"></category><category term="Datasette"></category><category term="Graphs"></category><category term="SQL"></category></entry><entry><title>2023, Semaine 42</title><link href="https://blog.notmyidea.org/2023-semaine-42.html" rel="alternate"></link><published>2023-10-23T00:00:00+02:00</published><updated>2023-10-23T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-10-23:/2023-semaine-42.html</id><summary type="html">
|
||
<p>J&#8217;ai passé la majeure partie de ma semaine seul, ponctuée par quelques ballades en bord de mer. J&#8217;ai pu reprendre contact avec la technologie et bien avancer sur le projet&nbsp;Argos.</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong>Framasoft /&nbsp;Argos</strong></dt>
|
||
<dd>Quatrième et dernière semaine rémunérée sur le projet. Je suis …</dd></dl></summary><content type="html">
|
||
<p>J&#8217;ai passé la majeure partie de ma semaine seul, ponctuée par quelques ballades en bord de mer. J&#8217;ai pu reprendre contact avec la technologie et bien avancer sur le projet&nbsp;Argos.</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong>Framasoft /&nbsp;Argos</strong></dt>
|
||
<dd>Quatrième et dernière semaine rémunérée sur le projet. Je suis très content de là ou en est le projet. J&#8217;ai pris le temps d&#8217;ajouter de l&#8217;intégration continue, des tests et de la&nbsp;documentation.</dd>
|
||
<dd>J&#8217;ai passé plus de temps que prévu à installer et à rendre fonctionnel PostgreSQL sur ma machine, et je me souviens que c&#8217;est souvent le cas pour moi. J&#8217;ai fini par écrire un mini tutoriel dans la documentation à ce propos, en espérant que ça&nbsp;serve.</dd>
|
||
<dd>J&#8217;ai pu tester l&#8217;installation et l&#8217;utilisation de l&#8217;outil sur plusieurs systèmes d&#8217;exploitation, et en même temps tester la virtualisation <span class="caps">QEMU</span> depuis mon&nbsp;ordinateur.</dd>
|
||
<dd>J&#8217;ai passé du temps à écrire des requêtes <span class="caps">SQL</span> avec SQLAlchemy, en trouvant ça beaucoup plus compliqué que de&nbsp;raison…</dd>
|
||
<dd>On a pu se faire une réunion de fin où j&#8217;ai validé avec Luc que le travail effectué correspondait bien à leurs attentes. Je suis content de réaliser que les choix techniques faits permettent d&#8217;avoir une performance satisfaisante et de pouvoir tester toute l&#8217;infrastructure depuis une seule&nbsp;machine.</dd>
|
||
<dt><strong>Umap</strong></dt>
|
||
<dd>le tuilage est presque parfait puisque je vais pouvoir commencer à travailler sur Umap début Novembre. L&#8217;idée est de travailler à une solution autour de la synchronisation de données géographiques. Je vous en dis plus&nbsp;bientôt.</dd>
|
||
<dd>J&#8217;ai pris le temps d&#8217;installer l&#8217;outil et de commencer à me familiariser avec le&nbsp;code.</dd>
|
||
<dd>J&#8217;ai commencé à passer en revue des projets qui font de la synchronisation de données en temps&nbsp;réel.</dd>
|
||
<dt><strong>Notmyidea</strong></dt>
|
||
<dd>J&#8217;ai passé du temps à me renseigner sur les protocoles <span class="caps">VPN</span> et leurs alternatives. J&#8217;ai rencontré Wireguard qui me semble être une approche minimaliste et&nbsp;sécure.</dd>
|
||
<dd>Je continue d&#8217;osciller à propos du statut juridique à adopter pour mon activité pro. Je me fixe la semaine prochaine&nbsp;:-)</dd>
|
||
</dl>
|
||
<h2 id="des-joies">Des&nbsp;joies</h2>
|
||
<ul>
|
||
<li>Passer du temps seul, apprécier le silence et le manque de sollicitations. L&#8217;organisation quotidienne est quand même grandement&nbsp;simplifiée.</li>
|
||
<li>Me promener et découvrir des espèces d&#8217;oiseaux que je ne connaissais pas, à mon propre&nbsp;rythme.</li>
|
||
<li>Assumer mon rapport à la technologie auprès de tiers. « Oui, je suis un geek et je crois qu&#8217;il ne faut pas laisser la technologie uniquement aux puissant•es&nbsp;».</li>
|
||
<li>Rentrer chez moi et être content de retrouver certaines dynamiques&nbsp;collectives.</li>
|
||
<li>Réussir à clarifier mes besoins en avance pour permettre d&#8217;éviter une frustration qui aurait pu arriver&nbsp;sinon.</li>
|
||
<li>Revenir sur des conflits passés et pouvoir en parler avec du recul, et avec une analyse différente, en utilisant une approche&nbsp;systémique.</li>
|
||
<li>Réussir à écouter une conversation et ne donner mon avis que si on me le&nbsp;demande.</li>
|
||
<li>Revivre des effluves d&#8217;été, à la fois posé en haut de la pointe du Roselier (St Brieuc), à la fois en voyant <a href="https://www.youtube.com/watch?v=2JEZLOaDKus&amp;feature=youtu.be">l&#8217;after-movie du festival l&#8217;Été de&nbsp;Vaour</a></li>
|
||
<li>Avoir un remerciement pour une position pas évidente que j&#8217;ai eu avec un ami il y a quelques années, avec du recul. Ça soigne&nbsp;:-)</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des&nbsp;peines</h2>
|
||
<ul>
|
||
<li>Voir les réactions viriles et bloquantes de certains hommes dans le public durant des&nbsp;concerts.</li>
|
||
<li>Intervenir pour « gérer un mec bourré » en soirée qui semblait ne pas comprendre que son comportement était déplacé. Je suis content de la manière dont les choses se sont passées, mais triste de voir qu&#8217;on en est toujours&nbsp;là.</li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>🎵 J&#8217;ai découvert deux groupes en live : <a href="https://fr.wikipedia.org/wiki/The_Inspector_Cluzo">The inspector Cluzo</a> et <a href="https://www.wikiwand.com/fr/Ko_Ko_Mo_(groupe_de_rock_fran%C3%A7ais)">Kokomo</a> durant un festival. J&#8217;ai beaucoup aimé l&#8217;émotion qui ressortait des deux, si on mets de côté le côté un peu viril qui peut parfois en sortir. Ça fait du bien de voir de la musique&nbsp;live.</li>
|
||
<li>🗯️ <a href="https://www.youtube.com/watch?v=zYoPYLqWcp4&amp;themeRefresh=1">Julia Cagé, François Ruffin, Thomas Piketty sur Médiapart</a>. J&#8217;ai trouvé les analyses de Julia Cagé et Thomas Piketty intéressante, mais malheureusement le ton de Ruffin assez fatiguant. Ça doit être fatiguant de ne pas répondre aux questions qu&#8217;on se fait poser. Malgré tout une vidéo&nbsp;intéressante.</li>
|
||
<li>📖 J&#8217;ai lu <a href="https://arenes.fr/livre/paroles-dhonneur/">Paroles d&#8217;honneur</a> de Leïla Slimani et Laetitia Coryn, qui parle du rapport à la sexualité au Maroc. J&#8217;ai beaucoup aimé à la fois le discours, le ton et les&nbsp;illustrations.</li>
|
||
<li>▶︎ <a href="https://www.youtube.com/watch?v=w6PLAmhjt50">La <span class="caps">MISERE</span> des hommes <span class="caps">SOUS</span> <span class="caps">LES</span> <span class="caps">DRAPS</span></a> et <a href="https://www.youtube.com/watch?v=cb7zlAkiSGw"><span class="caps">ETRE</span> <span class="caps">UN</span> <span class="caps">HOMME</span> : L&#8217;homme alpha</a>, deux vidéos de Léo, qui parlent respectivement de la « misère sexuelle » et de la compétition entre hommes. Plusieurs bouts font écho chez moi, sur des questions qui m&#8217;animent depuis longtemps autour de la&nbsp;compétition.</li>
|
||
</ul>
|
||
<h2 id="technique">Technique</h2>
|
||
<ul>
|
||
<li>J&#8217;ai été content de lire ce document qui introduit les <span class="caps">CRDT</span> en 2019&nbsp;https://www.inkandswitch.com/local-first/</li>
|
||
<li>Anthropic semble réussir à <a href="https://nitter.net/anthropicai/status/1709986949711200722">isoler les neurones d&#8217;un réseau neuronal</a> pour qu&#8217;ils se spécialisent sur une seule tache, grace à de l&#8217;apprentissage par dictionnaire&nbsp;;</li>
|
||
<li>Simon Willison <a href="https://simonwillison.net/2023/May/2/download-esm/">à fait un outil qui permet de récupérer une version ECMAScript d&#8217;une bibliothèque <span class="caps">JS</span> de votre choix</a>, en passant par npm et jsdelivr, et David Larlet <a href="https://gitlab.com/davidbgk/umap-stats/-/blob/main/npm.py">à fait quelque chose de similaire</a>, qui s&#8217;intègre facilement aux fichiers <code>pyproject.toml</code> utiles en&nbsp;python)</li>
|
||
<li><a href="https://drivendata.co/blog/python-packaging-2023">Une explication de l&#8217;état du packaging en python</a> qui m&#8217;a fait du bien. J&#8217;ai fait un <abbr title="Google Summer of Code"><span class="caps">GSOC</span></abbr> en 2010 — il y a 13 ans ! — sur le sujet du packaging, je suis content de voir que ça à beaucoup avancé, mais malheureusement que les choses ne sont pas encore très simples à&nbsp;comprendre.</li>
|
||
<li>Une vidéo de SimonW <a href="https://www.youtube.com/watch?v=qw4PrtyvJI0&amp;t=24953s">ou il résumé l&#8217;année qu&#8217;on vient de passer du point de vue de l&#8217;<span class="caps">AI</span></a></li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>Using DISTINCT in Parent-Child Relationships</title><link href="https://blog.notmyidea.org/using-distinct-in-parent-child-relationships.html" rel="alternate"></link><published>2023-10-18T00:00:00+02:00</published><updated>2023-10-18T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-10-18:/using-distinct-in-parent-child-relationships.html</id><summary type="html"><p>Let&#8217;s say you have a model defined like this, with a Parent and a Child&nbsp;table:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
|
||
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s2">&quot;parent&quot;</span>
|
||
<span class="nb">id</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column</span><span class="p">(</span><span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
|
||
<span class="n">childs</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="s2">&quot;Child&quot;</span><span class="p">]]</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="n">back_populates</span><span class="o">=</span><span class="s2">&quot;parent&quot;</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
|
||
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s2">&quot;child&quot;</span>
|
||
<span class="nb">id</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column</span><span class="p">(</span><span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="n">parent_id</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column …</span></code></pre></div></summary><content type="html"><p>Let&#8217;s say you have a model defined like this, with a Parent and a Child&nbsp;table:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Parent</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
|
||
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s2">&quot;parent&quot;</span>
|
||
<span class="nb">id</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column</span><span class="p">(</span><span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
|
||
<span class="n">childs</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="s2">&quot;Child&quot;</span><span class="p">]]</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="n">back_populates</span><span class="o">=</span><span class="s2">&quot;parent&quot;</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">Child</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
|
||
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s2">&quot;child&quot;</span>
|
||
<span class="nb">id</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column</span><span class="p">(</span><span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="n">parent_id</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column</span><span class="p">(</span><span class="n">ForeignKey</span><span class="p">(</span><span class="s2">&quot;parent.id&quot;</span><span class="p">))</span>
|
||
<span class="n">parent</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="s2">&quot;Parent&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="n">back_populates</span><span class="o">=</span><span class="s2">&quot;children&quot;</span><span class="p">)</span>
|
||
|
||
<span class="n">born_at</span><span class="p">:</span> <span class="n">Mapped</span><span class="p">[</span><span class="n">datetime</span><span class="p">]</span> <span class="o">=</span> <span class="n">mapped_column</span><span class="p">()</span>
|
||
</code></pre></div>
|
||
|
||
<p>I&#8217;ve tried many ways, with complex subqueries and the like, before finding out <a href="https://www.sqlitetutorial.net/sqlite-distinct/">the <span class="caps">DISTINCT</span> <span class="caps">SQL</span> statement</a>.</p>
|
||
<p>So, if you want to retrieve the parent with it&#8217;s more recent child, you can do it like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">results</span> <span class="o">=</span> <span class="p">(</span>
|
||
<span class="n">db</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Parent</span><span class="p">,</span> <span class="n">Child</span><span class="p">)</span>
|
||
<span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">Child</span><span class="p">)</span>
|
||
<span class="o">.</span><span class="n">distinct</span><span class="p">(</span><span class="n">Parent</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
|
||
<span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">Parent</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">desc</span><span class="p">(</span><span class="n">Child</span><span class="o">.</span><span class="n">born_at</span><span class="p">))</span>
|
||
<span class="o">.</span><span class="n">all</span><span class="p">()</span>
|
||
<span class="p">)</span>
|
||
</code></pre></div></content><category term="code"></category><category term="SQL"></category><category term="SQLAlchemy"></category><category term="Python"></category></entry><entry><title>2023, Semaine 41</title><link href="https://blog.notmyidea.org/2023-semaine-41.html" rel="alternate"></link><published>2023-10-16T00:00:00+02:00</published><updated>2023-10-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-10-16:/2023-semaine-41.html</id><summary type="html">
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong>Framasoft /&nbsp;Argos</strong></dt>
|
||
<dd>Troisième semaine de travail sur le projet. Tous les <strong>checks</strong> sont maintenant implémentés, et la structure du projet est surement&nbsp;définitive.</dd>
|
||
<dd>J&#8217;ai continué de travailler en mode chantier, à structurer ce qui devait l&#8217;être, et je suis plutôt satisfait du résultat …</dd></dl></summary><content type="html">
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong>Framasoft /&nbsp;Argos</strong></dt>
|
||
<dd>Troisième semaine de travail sur le projet. Tous les <strong>checks</strong> sont maintenant implémentés, et la structure du projet est surement&nbsp;définitive.</dd>
|
||
<dd>J&#8217;ai continué de travailler en mode chantier, à structurer ce qui devait l&#8217;être, et je suis plutôt satisfait du résultat. Les choix faits en terme de modèle de données me semblent pertinents en avançant sur le&nbsp;sujet.</dd>
|
||
<dd>J&#8217;ai passé trop de temps sur un bout de code qui est vraiment secondaire. Je l&#8217;ai vu mais je n&#8217;ai pas réussi à faire les choses « à moitié », pour avancer sur ce qui me paraissait&nbsp;important.</dd>
|
||
<dd>Je me suis heurté aux limites d&#8217;utiliser un micro-framework comme FastAPI, dans lequel il faut faire les choses soi même, et prendre des choix éclairés pour ce qui n&#8217;est pas intégré, comme par exemple l&#8217;intégration avec les bases de données. Je découvre tardivement l&#8217;existence d&#8217;une bibliothèque qui semble faire ce que je veux de manière optimale (<a href="https://github.com/encode/databases">Databases</a>).</dd>
|
||
<dd>J&#8217;ai pris du temps pour ajouter un minimum de tests unitaires sur la base de code, et ça m&#8217;a permis de detecter des&nbsp;bugs.</dd>
|
||
<dt><strong>Umap</strong></dt>
|
||
<dd>Je vais sans doute travailler avec David et Yohan sur <a href="https://github.com/umap-project/umap">Umap</a>, pour permettre l&#8217;édition collaborative de cartes en temps&nbsp;réel.</dd>
|
||
<dd>On a eu une première discussion sur le projet, pour échanger sur notre manière d&#8217;envisager ce temps de travail ensemble. Je le vois comme un projet de R&amp;D appliqué, et il semble possible de prendre le temps de se poser les bonnes questions avant d&#8217;avancer sur une implémentation concrète. C&#8217;est un bon moyen pour moi de continuer l&#8217;apprentissage entamé avec Kinto sur la synchronisation de&nbsp;données. </dd>
|
||
</dl>
|
||
<h2 id="des-joies">Des&nbsp;joies</h2>
|
||
<ul>
|
||
<li>Voir que j&#8217;arrive à parler de ce qui s&#8217;est passé pour moi durant ces derniers mois avec de plus en plus de recul et de clarté&nbsp;;</li>
|
||
<li>Observer les oiseaux et profiter de la faune et la flore sauvage de Bretagne&nbsp;;</li>
|
||
<li>Passer un week-end entre amis en tout simplicité à discuter, manger, jouer se ballader… Je suis content de reprendre pied sur des choses aussi simples&nbsp;;</li>
|
||
<li>Me permettre d&#8217;être plus&nbsp;décousu</li>
|
||
<li>Travailler de manière un peu décousue, sur des plages de durées pas assez longues. Je sens que j&#8217;ai quand même besoin d&#8217;au moins 4 heures de suite pour être&nbsp;efficace.</li>
|
||
<li>M&#8217;autoriser à faire une visio depuis mon&nbsp;jardin</li>
|
||
<li>Dormir dans un nouveau lieux de mon quotidien, et me sentir reposé au&nbsp;réveil…</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des&nbsp;peines</h2>
|
||
<ul>
|
||
<li>… Et en même temps ça veut dire que je ne dors pas bien dans mon logement&nbsp;actuel.</li>
|
||
<li>Ne pas avoir repris le sport. Je me trouve des excuses pour procrastiner, et je le ressens dans mon&nbsp;corps.</li>
|
||
<li>Ne pas prendre assez le temps de lire. Trop d&#8217;écrans le soir&nbsp;:-)</li>
|
||
<li>Sentir que je manque de clarté quand je m&#8217;exprime. J&#8217;aurai aimé mieux préparer ce temps. J&#8217;en sors avec une impression de discussion&nbsp;décousue. </li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>🎧 Fabrice Arfi qui parle de l&#8217;affaire Sarkozy/Kadafi et des financements de sa campagne présidentielle, ainsi que des liens avec la dictature Libyenne, dans <a href="https://podcast.crapouillou.net/#ostpolitik">la matinale d&#8217;<span class="caps">OST</span></a>. Je n&#8217;avais pas suivi du tout cette affaire, et j&#8217;en reste bouche&nbsp;bée.</li>
|
||
<li>🎧 Je me suis mis du coup à écouter la matinale d&#8217;<span class="caps">OST</span> en podcast (merci Jocelyn de mettre ça à dispo). Peut-être un bon moyen d&#8217;avoir de l&#8217;info avec un traitement médiatique correct. A suivre&nbsp;:-)</li>
|
||
<li>🎧 J&#8217;ai écouté <a href="https://soundcloud.com/user-645992042/georgie-ta-polyphonie-nous-3?in=user-645992042%2Fsets%2Fgeorgie-ta-polyphonie-nous-relie">Georgie Ta Polyphonie Nous Relie, <span class="caps">EP1</span> La Voix Libre</a>, un épisode de podcast réalisé sur des stages de chants organisés par Tinatine. J&#8217;aime le rapport qui y est posé à la voix et aux&nbsp;vibrations.</li>
|
||
<li>🍿 J&#8217;ai regardé quelques épisodes de la deuxième saison de <a href="https://fr.wikipedia.org/wiki/The_Good_Place">The Good Place</a>. Le faire avec un peu de recul lui apporte un peu de fraicheur : j&#8217;ai tendance à oublier le second degré si je regarde les épisodes trop proches les uns des&nbsp;autres.</li>
|
||
<li>🃏 J&#8217;ai découvert deux jeux : <a href="https://www.spacecowboys.fr/splendor">Splendor</a> et <a href="https://www.trictrac.net/jeu-de-societe/la-gloire-de-rome">La Gloire de Rome</a>. Clairement pas les meilleurs en termes d&#8217;éthique (les deux sont très colonialistes et patriarcaux), mais j&#8217;ai beaucoup aimé découvrir des dynamiques de jeux. Notamment avec La Gloire de Rome qui mets en avant la recherche de&nbsp;combos.</li>
|
||
<li>📖 J&#8217;ai continué <a href="https://editions-b42.com/produit/le-conflit-nest-pas-une-agression/">Le conflit n&#8217;est pas une agression</a> de Sarah&nbsp;Schulmann.</li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>Convert string to duration</title><link href="https://blog.notmyidea.org/convert-string-to-duration.html" rel="alternate"></link><published>2023-10-11T00:00:00+02:00</published><updated>2023-10-11T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-10-11:/convert-string-to-duration.html</id><summary type="html"><p>I found myself wanting to convert a string to a duration (int), for some&nbsp;configuration.</p>
|
||
<p>Something you can call like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;1d&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;days&quot;</span><span class="p">)</span>
|
||
<span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;1d&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;hours&quot;</span><span class="p">)</span>
|
||
<span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;3m&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;hours&quot;</span><span class="p">)</span>
|
||
<span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;3m&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;minutes&quot;</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>The code&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Literal</span>
|
||
|
||
<span class="k">def</span> <span class="nf">string_to_duration</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">target</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s2">&quot;days …</span></code></pre></div></summary><content type="html"><p>I found myself wanting to convert a string to a duration (int), for some&nbsp;configuration.</p>
|
||
<p>Something you can call like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;1d&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;days&quot;</span><span class="p">)</span>
|
||
<span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;1d&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;hours&quot;</span><span class="p">)</span>
|
||
<span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;3m&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;hours&quot;</span><span class="p">)</span>
|
||
<span class="n">string_to_duration</span><span class="p">(</span><span class="s2">&quot;3m&quot;</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="s2">&quot;minutes&quot;</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>The code&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Literal</span>
|
||
|
||
<span class="k">def</span> <span class="nf">string_to_duration</span><span class="p">(</span><span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">target</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s2">&quot;days&quot;</span><span class="p">,</span> <span class="s2">&quot;hours&quot;</span><span class="p">,</span> <span class="s2">&quot;minutes&quot;</span><span class="p">]):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Convert a string to a number of hours, days or minutes&quot;&quot;&quot;</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">isdigit</span><span class="p">,</span> <span class="n">value</span><span class="p">)))</span>
|
||
|
||
<span class="c1"># It&#39;s not possible to convert from a smaller unit to a greater one:</span>
|
||
<span class="c1"># - hours and minutes cannot be converted to days</span>
|
||
<span class="c1"># - minutes cannot be converted to hours</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">target</span> <span class="o">==</span> <span class="s2">&quot;days&quot;</span> <span class="ow">and</span> <span class="p">(</span><span class="s2">&quot;h&quot;</span> <span class="ow">in</span> <span class="n">value</span> <span class="ow">or</span> <span class="s2">&quot;m&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;mo&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)))</span> <span class="ow">or</span> <span class="p">(</span>
|
||
<span class="n">target</span> <span class="o">==</span> <span class="s2">&quot;hours&quot;</span> <span class="ow">and</span> <span class="s2">&quot;m&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;mo&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span>
|
||
<span class="p">):</span>
|
||
<span class="n">msg</span> <span class="o">=</span> <span class="p">(</span>
|
||
<span class="s2">&quot;Durations cannot be converted from a smaller to a greater unit. &quot;</span>
|
||
<span class="sa">f</span><span class="s2">&quot;(trying to convert &#39;</span><span class="si">{</span><span class="n">value</span><span class="si">}</span><span class="s2">&#39; to </span><span class="si">{</span><span class="n">target</span><span class="si">}</span><span class="s2">)&quot;</span>
|
||
<span class="p">)</span>
|
||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
|
||
<span class="c1"># Consider we&#39;re converting to minutes, do the eventual multiplication at the end.</span>
|
||
<span class="k">if</span> <span class="s2">&quot;h&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">*</span> <span class="mi">60</span>
|
||
<span class="k">elif</span> <span class="s2">&quot;d&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">24</span>
|
||
<span class="k">elif</span> <span class="s2">&quot;w&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">7</span>
|
||
<span class="k">elif</span> <span class="s2">&quot;mo&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">30</span> <span class="c1"># considers 30d in a month</span>
|
||
<span class="k">elif</span> <span class="s2">&quot;y&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">365</span>
|
||
<span class="k">elif</span> <span class="s2">&quot;m&quot;</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Invalid duration value&quot;</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">target</span> <span class="o">==</span> <span class="s2">&quot;hours&quot;</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">/</span> <span class="mi">60</span>
|
||
<span class="k">elif</span> <span class="n">target</span> <span class="o">==</span> <span class="s2">&quot;days&quot;</span><span class="p">:</span>
|
||
<span class="n">num</span> <span class="o">=</span> <span class="n">num</span> <span class="o">/</span> <span class="mi">60</span> <span class="o">/</span> <span class="mi">24</span>
|
||
|
||
<span class="k">return</span> <span class="n">num</span>
|
||
</code></pre></div></content><category term="code"></category><category term="python"></category><category term="conversion"></category></entry><entry><title>2023, Semaine 40</title><link href="https://blog.notmyidea.org/2023-semaine-40.html" rel="alternate"></link><published>2023-10-08T00:00:00+02:00</published><updated>2023-10-08T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-10-08:/2023-semaine-40.html</id><summary type="html">
|
||
<p>Je me suis réservé les matins pour travailler, et je suis content du rythme que ça à donné à ma semaine. C&#8217;était aussi le retour des pomodoros&nbsp;!</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong>Framasoft /&nbsp;Argos</strong></dt>
|
||
<dd>J&#8217;ai une première version quasiment fonctionnelle, il reste maintenant à transformer l&#8217;essai. J …</dd></dl></summary><content type="html">
|
||
<p>Je me suis réservé les matins pour travailler, et je suis content du rythme que ça à donné à ma semaine. C&#8217;était aussi le retour des pomodoros&nbsp;!</p>
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt><strong>Framasoft /&nbsp;Argos</strong></dt>
|
||
<dd>J&#8217;ai une première version quasiment fonctionnelle, il reste maintenant à transformer l&#8217;essai. J&#8217;ai pris le parti d&#8217;implémenter les choses au plus direct et de laisser des commentaires sur les choses qui seront à modifier plus loin dans le&nbsp;processus.</dd>
|
||
<dd>J&#8217;ai repensé encore une fois le modèle de données pour arriver à quelque chose qui me semble plus simple et&nbsp;pratique.</dd>
|
||
<dd>La première version de l&#8217;<span class="caps">API</span> est prête, et les workers peuvent la consommer, j&#8217;ai commencé à coder les premiers <em>checks</em>. J&#8217;ai un peu galéré avec Pydantic parce que je ne connais pas encore très bien l&#8217;outil, j&#8217;espère que ce sont des efforts qui vont payer sur le long&nbsp;terme.</dd>
|
||
<dt><strong>Le groupe, le&nbsp;jeu</strong></dt>
|
||
<dd>Troisième journée de travail avec Sam sur notre projet de jeu vidéo textuel. C&#8217;était toujours aussi plaisant de travailler&nbsp;ensemble.</dd>
|
||
<dd>On a mis en place des outils pour faciliter la génération des textes. Malheureusement, les modèles de données en local qu&#8217;on a pu essayer n&#8217;étaient pas au niveau de ce qu&#8217;on arrive à sortir avec <span class="caps">GPT4</span>.</dd>
|
||
<dd>J&#8217;ai commencé l&#8217;interface web en utilisant Elm et c&#8217;est toujours aussi&nbsp;plaisant.</dd>
|
||
</dl>
|
||
<h2 id="des-joies">Des&nbsp;joies</h2>
|
||
<ul>
|
||
<li>Profiter du soleil le temps d&#8217;une conversation téléphonique avec une amie. Aimer prendre le temps de se&nbsp;parler.</li>
|
||
<li>Sentir que je suis moins exposé au stress de ces dernières années, ça me fait vraiment du bien de me dire qu&#8217;un autre quotidien est&nbsp;possible.</li>
|
||
<li>Prévoir un voyage de fin d&#8217;année à l&#8217;avance. J&#8217;étais stressé de ne pas réussir à trouver les billets que je voulais, et le faire à l&#8217;avance me&nbsp;décharge.</li>
|
||
<li>Recevoir un appel où on me propose de travailler avec des gens que j&#8217;affectionne, sur un projet qui me plait, à un rythme raisonnable. Je vous en dis plus bientôt, mais ça fait au moins du bien à mon&nbsp;égo.</li>
|
||
<li>Voir que temporiser et discuter permet de résoudre des conflit en cours au sein de mon collectif de vie. En créant de l&#8217;empathie les un•e•s pour les autres, et sans trop arrondir les&nbsp;angles.</li>
|
||
<li>Découvrir que mon espace de travail à prévu un concert sur le temps du midi, en&nbsp;profiter.</li>
|
||
<li>M&#8217;autoriser à partir dans des situations qui générent de l&#8217;agacement chez moi, sans sentir de&nbsp;culpabilité.</li>
|
||
<li>Voir qu&#8217;il est possible de se dire les choses sans que ce soit mal pris dans le cadre d&#8217;un engagement bénévole&nbsp;logiciel.</li>
|
||
<li>Demander des clarifications sur des propositions qui em sont faites pour pouvoir mieux&nbsp;décider.</li>
|
||
<li>Imprimer mon premier prototype de coque de protection pour mon téléphone, au fablab du&nbsp;coin.</li>
|
||
<li>Expliquer le fonctionnement d&#8217;outils techniques à une personne intéressée, sentir qu&#8217;elle s&#8217;en&nbsp;empare.</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des&nbsp;peines</h2>
|
||
<ul>
|
||
<li>Voir plusieurs personnes qui forcent le passage durant un concert. J&#8217;aimerai réussir à passer outre, ou à&nbsp;réagir.</li>
|
||
<li>Sentir que certaines plaies récentes se réactivent en présence d&#8217;une personne pour qui j&#8217;ai du ressentiment. Ça prendra le temps qu&#8217;il&nbsp;faut.</li>
|
||
<li>Être frustré par une décision alors qu&#8217;elle ne me concerne pas&nbsp;vraiment.</li>
|
||
<li>Me sentir pris au piège d&#8217;une conversation qui ne m&#8217;intéresse pas vraiment. Ne pas réussir à changer le&nbsp;sujet.</li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>📖 J&#8217;ai continué <a href="https://editions-b42.com/produit/le-conflit-nest-pas-une-agression/">Le conflit n&#8217;est pas une agression</a> de Sarah Schulmann. J&#8217;y ai trouvé des billes concrètes, et une mise en question du mécanisme de blocage de la conversation qui peut avoir lieu dans certains conflits (et auquel j&#8217;ai pu avoir recours par le passé). J&#8217;aime globalement beaucoup cette&nbsp;lecture.</li>
|
||
<li>📖 Bientôt terminé <a href="https://grand-monde.fr/">Quelqu&#8217;un à qui manquer</a> de Yohan Boniface. J&#8217;aime beaucoup me retrouver dans la peau d&#8217;un enfant dans un pays que je ne connais pas. Toutes ces expressions et la manière de raconter avec des mots enfantins, c&#8217;est assez&nbsp;magique.</li>
|
||
<li>📖 J&#8217;ai récupéré le dernier tome de <a href="https://lavilaine-edition.com/">La Vilaine</a>, et je l&#8217;ai dévoré. Je l&#8217;ai trouvé encore plus réussi que les premiers numéros. C&#8217;est très chouette de voir des intrigues se dérouler dans sa ville, et d&#8217;y trouver des moments&nbsp;partagés.</li>
|
||
<li>🎧 <a href="https://www.binge.audio/podcast/les-couilles-sur-la-table/05-sortir-de-la-justice-punitive">Sortir de la justice punitive (Les couilles sur la table)</a> avec Elsa Deck Marsault. Ça vient questionner notre gestion du conflit dans les sphères « de gauche » et militantes. J&#8217;aime beaucoup l&#8217;écho entre ce podcast et le livre de Sarah&nbsp;Schulmann</li>
|
||
<li>🕸️ <a href="https://lessoulevementsdelaterre.org/blog/affaire-lafarge.les-moyens-denquete-utilises-et-quelques-attentions-a-en-tirer">Un article qui explique les moyens déployés pour faire de la surveillance dans l&#8217;affaire Lafarge</a>. Beaucoup de choses intéressantes dans l&#8217;article. En fait c&#8217;est aussi effrayant que passionnant. Je ne pensais pas que les relevés téléphoniques pouvaient être utilisés aussi facilement par&nbsp;exemple.</li>
|
||
<li>🪗 Un concert de <a href="https://fr.wikipedia.org/wiki/La_Yegros">La Yegros</a>, et de <a href="https://www.youtube.com/watch?v=Zap5hzpjp4A">Sidi Watcho</a> au grand&nbsp;soufflet.</li>
|
||
<li>🪗 Un concert de <a href="https://www.compagnie-aziade.fr/victoria-delaroziere/">Victoria Delarozière</a> à la&nbsp;Canopée</li>
|
||
<li>🍿 J&#8217;ai continué et bientôt terminé <a href="https://www.france.tv/france-2/abysses/">Abysses</a>. J&#8217;aime bien le pitch de départ, mais les choses s&#8217;essouflent un peu. C&#8217;est dommage sur 8&nbsp;épisodes.</li>
|
||
<li>🍿 Vu <a href="https://fr.wikipedia.org/wiki/La_Favorite_(film)">La favorite</a>, avec Olivia Coleman. C&#8217;était… difficile de voir toute cette manipulation à l&#8217;œuvre, et en même temps intéressant de le voir&nbsp;documenté.</li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>2023, Semaine 39</title><link href="https://blog.notmyidea.org/2023-semaine-39.html" rel="alternate"></link><published>2023-09-29T00:00:00+02:00</published><updated>2023-09-29T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-29:/2023-semaine-39.html</id><summary type="html">
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt>Framasoft</dt>
|
||
<dd>J&#8217;ai commencé à travailler sur l&#8217;outil de supervision, en partant bille en tête sur une solution qui s&#8217;est avérée ne pas être la plus simple à mettre en place. J&#8217;ai passé pas mal de temps à questionner mes choix techniques …</dd></dl></summary><content type="html">
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt>Framasoft</dt>
|
||
<dd>J&#8217;ai commencé à travailler sur l&#8217;outil de supervision, en partant bille en tête sur une solution qui s&#8217;est avérée ne pas être la plus simple à mettre en place. J&#8217;ai passé pas mal de temps à questionner mes choix techniques, pour finalement en changer et me questionner sur la partie <strong>metier</strong>, ce qui me semblait plus intéressant. A partir du moment où j&#8217;ai arrêté d&#8217;essayer d&#8217;appliquer une solution « déjà faite » j&#8217;ai pu me questionner sur le modèle de données et aller de l&#8217;avant. Étrangement c&#8217;est quand j&#8217;ai produit le moins de code que j&#8217;ai trouvé que j&#8217;étais le plus&nbsp;productif.</dd>
|
||
<dt>Notmyidea</dt>
|
||
<dd>Je n&#8217;ai pas trop avancé sur la partie structure juridique, mais les choses décantent et me paraissent plus clair que la semaine passée. Je penche en ce moment pour une solution en auto-entreprise pour les quelques premières missions, quitte à remettre en question ce choix par la suite si je trouve de nouveaux·elles client·es. Je me laisse le temps pour&nbsp;décider.</dd>
|
||
<dd>J&#8217;ai <del>procrastiné</del> passé beaucoup plus de temps que prévu sur la mise en place d&#8217;outils utiles pour moi, et à peaufiné mon site web. J&#8217;ai maintenant un bouncer <span class="caps">ZNC</span> et un <span class="caps">VPN</span> fait maison qui me permettent de travailler dans de meilleures conditions. Je suis à la fois content d&#8217;avoir pris le temps de mettre en place des outils, et en même temps j&#8217;ai une impression de&nbsp;procrastination.</dd>
|
||
</dl>
|
||
<h2 id="des-joies">Des&nbsp;joies</h2>
|
||
<ul>
|
||
<li>Avoir pris le temps d&#8217;aller « à la ville » pour passer du temps avec des amis et&nbsp;sociabiliser.</li>
|
||
<li>M&#8217;écouter et décider de dormir sur place pour travailler aussi sur Rennes le&nbsp;lendemain.</li>
|
||
<li>Aller à l&#8217;espace de coworkig à côté de chez&nbsp;moi.</li>
|
||
<li>Prendre le temps de faire des choses peu importantes entassées dans ma todolist depuis trop&nbsp;longtemps.</li>
|
||
<li>Récolter des fruits de discussions passées lors d&#8217;une soirée. Vive les todo-list&nbsp;!</li>
|
||
<li>Voir qu&#8217;une demande de modifications que j&#8217;ai faite soit appréciée et intégrée&nbsp;rapidement.</li>
|
||
<li>Dépanner le serveur de <a href="https://github.com/almet/copanier">copanier</a>, trouver le problème rapidement et le régler&nbsp;facilement.</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des&nbsp;peines</h2>
|
||
<ul>
|
||
<li>Je suis retombé malade en fin de semaine, et donc bien fatigué. Ca impacte mon moral et ma capacité de&nbsp;concentration.</li>
|
||
<li>Des discussions compliquées dans mon collectif de vie. Je suis content de poser des limites, mais je sens que je cherche toujours la validation des&nbsp;autres.</li>
|
||
<li>Sentir que ma posture dans les conversations est plus ferme que par le passé. Je suis à la fois content de ne pas <strong>toujours</strong> me remettre en question, mais j&#8217;aimerai réussir à faire preuve de plus d&#8217;ouverture. Il faut trouver&nbsp;l&#8217;équilibre </li>
|
||
<li>Triste de voir des conflits escalader alors que ça pourrait être&nbsp;autrement.</li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>🎮 J&#8217;ai continué <a href="https://fr.wikipedia.org/wiki/Baba_Is_You">Baba is you</a> avec Arthur. C&#8217;était sympa de se faire les reflexions à deux&nbsp;cerveaux.</li>
|
||
<li>▶︎ <a href="https://www.youtube.com/watch?app=desktop&amp;v=dVzfNZN9NKI&amp;list=PL8uoeex94UhFcwvAfWHybD7SfNgIUBRo-&amp;index=128">Vu une présentation sur DuckDB</a>, une base de données locale et minimaliste qui semble adaptée pour de la visualisation de données à grande&nbsp;échelle.</li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>llm command-line tips</title><link href="https://blog.notmyidea.org/llm-command-line-tips.html" rel="alternate"></link><published>2023-09-27T00:00:00+02:00</published><updated>2023-09-27T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-27:/llm-command-line-tips.html</id><summary type="html"><p>I&#8217;m using <a href="https://llm.datasette.io">llm</a> more and more, and today I had to find back prompts I used in the past. Here is a command I&#8217;ve been using, which allows me to filter the results based on what I want. It leverages <a href="https://sqlutils.datasette.io">sql-utils</a>, a cli tool which is able to …</p></summary><content type="html"><p>I&#8217;m using <a href="https://llm.datasette.io">llm</a> more and more, and today I had to find back prompts I used in the past. Here is a command I&#8217;ve been using, which allows me to filter the results based on what I want. It leverages <a href="https://sqlutils.datasette.io">sql-utils</a>, a cli tool which is able to talk to a <span class="caps">SQLITE</span> database and answer in json, and <a href="https://github.com/jqlang/jq">jq</a> a command-line tool capable of doing requests for&nbsp;json.</p>
|
||
<p>All in all, it&#8217;s pretty satisfying to use. I finally got a simple way to query databases! I&#8217;m also using <a href="https://github.com/charmbracelet/glow">glow</a>, which is capable of transforming markdown into a better version on the&nbsp;terminal.</p>
|
||
<div class="highlight"><pre><span></span><code>sqlite-utils<span class="w"> </span><span class="s2">&quot;</span><span class="k">$(</span>llm<span class="w"> </span>logs<span class="w"> </span>path<span class="k">)</span><span class="s2">&quot;</span><span class="w"> </span><span class="s2">&quot;SELECT * FROM responses WHERE prompt LIKE &#39;%search%&#39;&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>jq<span class="w"> </span><span class="s1">&#39;.[].response&#39;</span><span class="w"> </span>-r<span class="w"> </span><span class="p">|</span><span class="w"> </span>glow
|
||
</code></pre></div>
|
||
|
||
<p>Which got me a colored response&nbsp;:-)</p></content><category term="code"></category><category term="python"></category><category term="llm"></category><category term="bash"></category><category term="sqlite"></category></entry><entry><title>Setting up a IRC Bouncer with ZNC</title><link href="https://blog.notmyidea.org/setting-up-a-irc-bouncer-with-znc.html" rel="alternate"></link><published>2023-09-27T00:00:00+02:00</published><updated>2023-09-27T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-27:/setting-up-a-irc-bouncer-with-znc.html</id><summary type="html"><p>It&#8217;s been a while since I&#8217;ve used <span class="caps">IRC</span>, but I needed to connect to it today to discuss around <a href="https://docs.peewee-orm.com">Peewee</a>.</p>
|
||
<p>The main issue with <span class="caps">IRC</span> is that you need to be connected to see the answer, and to get the context of the conversation. Unless&#8230; you set up …</p></summary><content type="html"><p>It&#8217;s been a while since I&#8217;ve used <span class="caps">IRC</span>, but I needed to connect to it today to discuss around <a href="https://docs.peewee-orm.com">Peewee</a>.</p>
|
||
<p>The main issue with <span class="caps">IRC</span> is that you need to be connected to see the answer, and to get the context of the conversation. Unless&#8230; you set up a&nbsp;bouncer.</p>
|
||
<p>The bouncer is named <a href="https://znc.in"><span class="caps">ZNC</span></a>, and the <span class="caps">IRC</span> client I use is <a href="https://weechat.org">Weechat</a>.</p>
|
||
<p>So, that&#8217;s what I&nbsp;did:</p>
|
||
<h2 id="installation-of-znc">Installation of <span class="caps">ZNC</span></h2>
|
||
<div class="highlight"><pre><span></span><code>apt<span class="w"> </span>install<span class="w"> </span>znc
|
||
sudo<span class="w"> </span>-u<span class="w"> </span>_znc<span class="w"> </span>/usr/bin/znc<span class="w"> </span>--datadir<span class="o">=</span>/var/lib/znc<span class="w"> </span>--makeconf
|
||
sudo<span class="w"> </span>systemctl<span class="w"> </span><span class="nb">enable</span><span class="w"> </span>znc
|
||
</code></pre></div>
|
||
|
||
<p>You can answer the questions asked by <code>--makeconf</code>, it will generate you a configuration file like this (stored in <code>/var/lib/znc/configurations/znc.conf</code>):</p>
|
||
<div class="highlight"><pre><span></span><code>AnonIPLimit<span class="w"> </span>=<span class="w"> </span>10
|
||
AuthOnlyViaModule<span class="w"> </span>=<span class="w"> </span>false
|
||
ConfigWriteDelay<span class="w"> </span>=<span class="w"> </span>0
|
||
ConnectDelay<span class="w"> </span>=<span class="w"> </span>5
|
||
HideVersion<span class="w"> </span>=<span class="w"> </span>false
|
||
LoadModule<span class="w"> </span>=<span class="w"> </span>webadmin
|
||
MaxBufferSize<span class="w"> </span>=<span class="w"> </span>500
|
||
ProtectWebSessions<span class="w"> </span>=<span class="w"> </span>true
|
||
SSLCertFile<span class="w"> </span>=<span class="w"> </span>/var/lib/znc/znc.pem
|
||
SSLDHParamFile<span class="w"> </span>=<span class="w"> </span>/var/lib/znc/znc.pem
|
||
SSLKeyFile<span class="w"> </span>=<span class="w"> </span>/var/lib/znc/znc.pem
|
||
ServerThrottle<span class="w"> </span>=<span class="w"> </span>30
|
||
Version<span class="w"> </span>=<span class="w"> </span>1.8.2
|
||
|
||
<span class="nt">&lt;Listener</span><span class="w"> </span><span class="err">listener0</span><span class="nt">&gt;</span>
|
||
<span class="w"> </span>AllowIRC<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>AllowWeb<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>IPv4<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>IPv6<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>Port<span class="w"> </span>=<span class="w"> </span>6697
|
||
<span class="w"> </span>SSL<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>URIPrefix<span class="w"> </span>=<span class="w"> </span>/
|
||
<span class="nt">&lt;/Listener&gt;</span>
|
||
|
||
<span class="nt">&lt;User</span><span class="w"> </span><span class="err">alexis</span><span class="nt">&gt;</span>
|
||
<span class="w"> </span>Admin<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>Allow<span class="w"> </span>=<span class="w"> </span>*
|
||
<span class="w"> </span>AltNick<span class="w"> </span>=<span class="w"> </span>alexis_
|
||
<span class="w"> </span>AppendTimestamp<span class="w"> </span>=<span class="w"> </span>false
|
||
<span class="w"> </span>AuthOnlyViaModule<span class="w"> </span>=<span class="w"> </span>false
|
||
<span class="w"> </span>AutoClearChanBuffer<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>AutoClearQueryBuffer<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>BindHost<span class="w"> </span>=<span class="w"> </span>skate.notmyidea.org
|
||
<span class="w"> </span>ChanBufferSize<span class="w"> </span>=<span class="w"> </span>50
|
||
<span class="w"> </span>DenyLoadMod<span class="w"> </span>=<span class="w"> </span>false
|
||
<span class="w"> </span>DenySetBindHost<span class="w"> </span>=<span class="w"> </span>false
|
||
<span class="w"> </span>Ident<span class="w"> </span>=<span class="w"> </span>alexis
|
||
<span class="w"> </span>JoinTries<span class="w"> </span>=<span class="w"> </span>10
|
||
<span class="w"> </span>LoadModule<span class="w"> </span>=<span class="w"> </span>chansaver
|
||
<span class="w"> </span>LoadModule<span class="w"> </span>=<span class="w"> </span>controlpanel
|
||
<span class="w"> </span>MaxJoins<span class="w"> </span>=<span class="w"> </span>0
|
||
<span class="w"> </span>MaxNetworks<span class="w"> </span>=<span class="w"> </span>1
|
||
<span class="w"> </span>MaxQueryBuffers<span class="w"> </span>=<span class="w"> </span>50
|
||
<span class="w"> </span>MultiClients<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>Nick<span class="w"> </span>=<span class="w"> </span>alexis
|
||
<span class="w"> </span>NoTrafficTimeout<span class="w"> </span>=<span class="w"> </span>180
|
||
<span class="w"> </span>PrependTimestamp<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>QueryBufferSize<span class="w"> </span>=<span class="w"> </span>50
|
||
<span class="w"> </span>QuitMsg<span class="w"> </span>=<span class="w"> </span>See<span class="w"> </span>you<span class="w"> </span>:)
|
||
<span class="w"> </span>RealName<span class="w"> </span>=<span class="w"> </span>N/A
|
||
<span class="w"> </span>StatusPrefix<span class="w"> </span>=<span class="w"> </span>*
|
||
<span class="w"> </span>TimestampFormat<span class="w"> </span>=<span class="w"> </span>[%H:%M:%S]
|
||
|
||
<span class="w"> </span><span class="nt">&lt;Network</span><span class="w"> </span><span class="err">liberachat</span><span class="nt">&gt;</span>
|
||
<span class="w"> </span>FloodBurst<span class="w"> </span>=<span class="w"> </span>9
|
||
<span class="w"> </span>FloodRate<span class="w"> </span>=<span class="w"> </span>2.00
|
||
<span class="w"> </span>IRCConnectEnabled<span class="w"> </span>=<span class="w"> </span>true
|
||
<span class="w"> </span>JoinDelay<span class="w"> </span>=<span class="w"> </span>0
|
||
<span class="w"> </span>LoadModule<span class="w"> </span>=<span class="w"> </span>simple_away
|
||
<span class="w"> </span>RealName<span class="w"> </span>=<span class="w"> </span>N/A
|
||
<span class="w"> </span>Server<span class="w"> </span>=<span class="w"> </span>irc.libera.chat<span class="w"> </span>+6697
|
||
<span class="w"> </span>TrustAllCerts<span class="w"> </span>=<span class="w"> </span>false
|
||
<span class="w"> </span>TrustPKI<span class="w"> </span>=<span class="w"> </span>true
|
||
|
||
<span class="w"> </span><span class="nt">&lt;Chan</span><span class="w"> </span><span class="err">#peewee</span><span class="nt">&gt;</span>
|
||
<span class="w"> </span><span class="nt">&lt;/Chan&gt;</span>
|
||
<span class="w"> </span><span class="nt">&lt;/Network&gt;</span>
|
||
|
||
<span class="w"> </span><span class="nt">&lt;Pass</span><span class="w"> </span><span class="err">password</span><span class="nt">&gt;</span>
|
||
<span class="w"> </span>Hash<span class="w"> </span>=<span class="w"> </span>REDACTED
|
||
<span class="w"> </span>Method<span class="w"> </span>=<span class="w"> </span>SHA256
|
||
<span class="w"> </span>Salt<span class="w"> </span>=<span class="w"> </span>REDACTED
|
||
<span class="w"> </span><span class="nt">&lt;/Pass&gt;</span>
|
||
<span class="nt">&lt;/User&gt;</span>
|
||
</code></pre></div>
|
||
|
||
<p>You can access a web interface on the exposed port. I had to make a change in my Firefox configuration, in <code>about:config</code>, set <code>network.security.ports.banned.override</code> to <code>6697</code>, otherwise, Firefox prevents you from connecting to these ports (which might actually be a good&nbsp;idea).</p>
|
||
<h2 id="weechat-configuration">Weechat&nbsp;configuration</h2>
|
||
<p>Now, to use this in weechat, here are some useful commands. First, get the fingerprint of the <span class="caps">SSL</span> certificate generated on your&nbsp;server:</p>
|
||
<div class="highlight"><pre><span></span><code>cat<span class="w"> </span>/var/log/znc/znc.pem<span class="w"> </span><span class="p">|</span><span class="w"> </span>openssl<span class="w"> </span>x509<span class="w"> </span>-sha512<span class="w"> </span>-fingerprint<span class="w"> </span>-noout<span class="w"> </span><span class="p">|</span><span class="w"> </span>tr<span class="w"> </span>-d<span class="w"> </span><span class="s1">&#39;:&#39;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>tr<span class="w"> </span><span class="s1">&#39;A-Z&#39;</span><span class="w"> </span><span class="s1">&#39;a-z&#39;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>cut<span class="w"> </span>-d<span class="w"> </span><span class="o">=</span><span class="w"> </span>-f<span class="w"> </span><span class="m">2</span>
|
||
</code></pre></div>
|
||
|
||
<p>Then, in weechat&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>/server add znc host/6697 -tls -username=&lt;username&gt; -password=&lt;yourpass&gt; -autoconnect
|
||
/set irc.server.znc.tls_fingerprint &lt;fingerprint-goes-here&gt;
|
||
/connect znc
|
||
</code></pre></div>
|
||
|
||
<p>And you should be all&nbsp;set!</p>
|
||
<p>Resources : <a href="https://wiki.znc.in/Weechat">The <span class="caps">ZNC</span> Wiki on Weechat</a> and the <a href="https://wiki.debian.org/ZNC">Debian page on <span class="caps">ZNC</span></a></p></content><category term="code"></category><category term="ZNC"></category><category term="Weechat"></category><category term="IRC"></category></entry><entry><title>2023, Semaine 38</title><link href="https://blog.notmyidea.org/2023-semaine-38.html" rel="alternate"></link><published>2023-09-24T00:00:00+02:00</published><updated>2023-09-24T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-24:/2023-semaine-38.html</id><summary type="html">
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt>Framasoft</dt>
|
||
<dd>J&#8217;ai eu confirmation que j&#8217;allais pouvoir commencer à travailler sur une mission pour <a href="https://framasoft.org">Framasoft</a>, pour faire un outil qui aide à la supervision de leurs services Web. C&#8217;est la première fois que je vais travailler en tant qu&#8217;indépendant et je …</dd></dl></summary><content type="html">
|
||
<h2 id="ce-qui-sest-passe">Ce qui s&#8217;est&nbsp;passé</h2>
|
||
<dl>
|
||
<dt>Framasoft</dt>
|
||
<dd>J&#8217;ai eu confirmation que j&#8217;allais pouvoir commencer à travailler sur une mission pour <a href="https://framasoft.org">Framasoft</a>, pour faire un outil qui aide à la supervision de leurs services Web. C&#8217;est la première fois que je vais travailler en tant qu&#8217;indépendant et je trouve ça assez&nbsp;exitant.</dd>
|
||
<dt>Le Groupe, le&nbsp;jeu</dt>
|
||
<dd>On s&#8217;est vu avec <a href="https://www.samuelgenin.fr/">Sam</a> pour commencer à bosser sur une idée de petit jeu textuel. Une session de travail sur tableau blanc le matin pour mettre nos idées au clair, suivie d&#8217;une après-midi à travailler sur des « prompts » pour des <a href="https://fr.wikipedia.org/wiki/Grand_mod%C3%A8le_de_langage"><span class="caps">LLM</span></a>. C&#8217;était vraiment un bon moment, et on a bien avancé. J&#8217;ai aussi passé un peu de temps en fin de semaine à mettre en place un projet en Elm avec Vite. Je suis content que ce projet me fasse réutiliser ces&nbsp;technos.</dd>
|
||
<dt>Notmyidea</dt>
|
||
<dd>Il va me falloir une structure juridique pour pouvoir émettre factures et devis. J&#8217;ai participé à une présentation de la <span class="caps">CAE</span> <a href="https://astrolabe.coop">Astrolabe</a>, qui me permette de mieux comprendre le fonctionnement de ce type de structures. Je ne suis pas encore décidé sur le type de structure que je vais&nbsp;adopter. </dd>
|
||
<dd>J&#8217;ai aussi passé du temps à remettre à jour mon site web&nbsp;perso.</dd>
|
||
<dd>J&#8217;ai migré mes mails vers <a href="https://nubo.coop">Nubo</a>, un hébergeur&nbsp;coopératif.</dd>
|
||
</dl>
|
||
<h2 id="des-joies">Des&nbsp;joies</h2>
|
||
<ul>
|
||
<li>J&#8217;ai pris le temps de faire plusieurs siestes au soleil. J&#8217;aime avoir la possibilité d&#8217;écouter mon&nbsp;rythme.</li>
|
||
<li>Choisir de ne pas aller à l&#8217;<span class="caps">AG</span> d&#8217;une association dont l&#8217;objet me semble intéressant, mais pour laquelle je n&#8217;ai pas beaucoup de temps à donner. Je suis content de faire ce&nbsp;choix.</li>
|
||
<li>Dépanner des ami·es sans que cela ne me coûte d&#8217;énergie. Je suis content de retrouver une certaine quiétude au&nbsp;quotidien.</li>
|
||
<li>Avoir au téléphone de vieilles connaissances et sentir que la relation est toujours&nbsp;intéressante.</li>
|
||
<li>Aller me poser à la bibliothèque pour&nbsp;travailler.</li>
|
||
</ul>
|
||
<h2 id="des-peines">Des&nbsp;peines</h2>
|
||
<ul>
|
||
<li>Devoir annuler plusieurs rendez-vous qui me tenaient à cœur à cause de la&nbsp;maladie.</li>
|
||
<li>Je me suis couché trop tard, et mon rythme est&nbsp;décallé.</li>
|
||
</ul>
|
||
<h2 id="vu-lu-ecoute">Vu, lu,&nbsp;écouté</h2>
|
||
<ul>
|
||
<li>▶︎ <a href="https://www.youtube.com/watch?v=kMb4TmhTlbk&amp;list=PL8uoeex94UhFcwvAfWHybD7SfNgIUBRo-&amp;index=135">Une présentation</a> de ce qu&#8217;il est possible de faire avec les <span class="caps">LLM</span> et les dernèières avancées en machine learning dans le domaine de la musique. J&#8217;ai trouvé ça&nbsp;bluffant.</li>
|
||
<li>📖 J&#8217;ai terminé la lecture de « Eloge de l&#8217;amitié » de Geoffroy de Lagasnerie. Beaucoup de choses intéressantes. J&#8217;ai publié <a href="https://notes.notmyidea.org/notes-litteraires/livres/geoffroy-de-lasganerie-eloge-de-l-amitie/">quelques notes de lecture ici</a>.</li>
|
||
<li>📖 Commencé « Le conflit n&#8217;est pas une agression » de Sarah Schulmann. Je sens que ça va faire bouger certaines choses chez&nbsp;moi.</li>
|
||
<li>📖 Commencé « Quelqu&#8217;un à qui manquer » de Yohan Boniface. J&#8217;aime beaucoup l&#8217;univers et le ton&nbsp;jusqu&#8217;ici.</li>
|
||
<li>🎮 Commencé « Baba is you », un petit jeu vidéo de logique. Divertissant&nbsp;:-)</li>
|
||
<li>🕸️ Un super article qui explique <a href="https://jzhao.xyz/posts/bft-json-crdt">comment fonctionnent les <span class="caps">CRDT</span> (Conflit-free Replicated Data Types)</a>, de manière très&nbsp;didactique.</li>
|
||
</ul></content><category term="weeknotes"></category></entry><entry><title>How to run the vigogne model locally</title><link href="https://blog.notmyidea.org/how-to-run-the-vigogne-model-locally.html" rel="alternate"></link><published>2023-09-22T00:00:00+02:00</published><updated>2023-09-22T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-22:/how-to-run-the-vigogne-model-locally.html</id><summary type="html">
|
||
<p><a href="https://github.com/bofenghuang/vigogne">Vigogne</a> is a <span class="caps">LLM</span> model based on <span class="caps">LLAMA2</span>, but trained with french data. As I&#8217;m working mostly in french, it might be useful. The current models that I can get locally are in&nbsp;english.</p>
|
||
<p>The information I&#8217;ve found online are scarse and not so easy to follow, so …</p></summary><content type="html">
|
||
<p><a href="https://github.com/bofenghuang/vigogne">Vigogne</a> is a <span class="caps">LLM</span> model based on <span class="caps">LLAMA2</span>, but trained with french data. As I&#8217;m working mostly in french, it might be useful. The current models that I can get locally are in&nbsp;english.</p>
|
||
<p>The information I&#8217;ve found online are scarse and not so easy to follow, so here is a step by step tutorial you can follow. I&#8217;m using <a href="https://pipenv.pypa.io/en/latest/">pipenv</a> almost everywhere now, it&#8217;s so easy&nbsp;:-)</p>
|
||
<div class="highlight"><pre><span></span><code>llm<span class="w"> </span>install<span class="w"> </span>-U<span class="w"> </span>llm-llama-cpp
|
||
wget<span class="w"> </span>https://huggingface.co/TheBloke/Vigogne-2-7B-Chat-GGUF/resolve/main/vigogne-2-7b-chat.Q4_K_M.gguf
|
||
llm<span class="w"> </span>llama-cpp<span class="w"> </span>add-model<span class="w"> </span>vigogne-2-7b-chat.Q4_K_M.gguf<span class="w"> </span>-a<span class="w"> </span>vigogne
|
||
llm<span class="w"> </span>models<span class="w"> </span>default<span class="w"> </span>vigogne
|
||
</code></pre></div></content><category term="code"></category><category term="llm"></category></entry><entry><title>Creating a simple command line to post snippets on Gitlab</title><link href="https://blog.notmyidea.org/creating-a-simple-command-line-to-post-snippets-on-gitlab.html" rel="alternate"></link><published>2023-09-18T00:00:00+02:00</published><updated>2023-09-18T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-18:/creating-a-simple-command-line-to-post-snippets-on-gitlab.html</id><summary type="html">
|
||
<p>I&#8217;m trying to get away from Github, and one thing that I find useful is the <a href="https://gist.github.com">gist</a> utility they&#8217;re providing. Seems that gitlab provides a similar&nbsp;tool.</p>
|
||
<p>You can use it using <a href="https://python-gitlab.readthedocs.io/">python-gitlab</a>:</p>
|
||
<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>python-gitlab
|
||
</code></pre></div>
|
||
|
||
<p>And then&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>gitlab<span class="w"> </span>snippet<span class="w"> </span>create<span class="w"> </span>--title<span class="o">=</span><span class="s2">&quot;youpi&quot;</span><span class="w"> </span>--file-name<span class="o">=</span><span class="s2">&quot;snip.py&quot;</span><span class="w"> </span>--content<span class="w"> </span>snip …</code></pre></div></summary><content type="html">
|
||
<p>I&#8217;m trying to get away from Github, and one thing that I find useful is the <a href="https://gist.github.com">gist</a> utility they&#8217;re providing. Seems that gitlab provides a similar&nbsp;tool.</p>
|
||
<p>You can use it using <a href="https://python-gitlab.readthedocs.io/">python-gitlab</a>:</p>
|
||
<div class="highlight"><pre><span></span><code>pipx<span class="w"> </span>install<span class="w"> </span>python-gitlab
|
||
</code></pre></div>
|
||
|
||
<p>And then&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>gitlab<span class="w"> </span>snippet<span class="w"> </span>create<span class="w"> </span>--title<span class="o">=</span><span class="s2">&quot;youpi&quot;</span><span class="w"> </span>--file-name<span class="o">=</span><span class="s2">&quot;snip.py&quot;</span><span class="w"> </span>--content<span class="w"> </span>snip.py<span class="w"> </span>--visibility<span class="o">=</span><span class="s2">&quot;public&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>I now wanted a small bash script which will just get the name of the file and infer all the parameters. I asked <span class="caps">GPT</span>-4, and iterated on its&nbsp;answer.</p>
|
||
<p>Here&#8217;s the resulting bash&nbsp;script:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="ch">#!/bin/bash</span>
|
||
|
||
<span class="k">if</span><span class="w"> </span><span class="o">[</span><span class="w"> </span>-z<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span><span class="w"> </span><span class="o">]</span>
|
||
<span class="k">then</span>
|
||
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;Please provide a filename&quot;</span>
|
||
<span class="w"> </span><span class="nb">exit</span><span class="w"> </span><span class="m">1</span>
|
||
<span class="k">fi</span>
|
||
|
||
<span class="nv">file</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$1</span><span class="s2">&quot;</span>
|
||
<span class="nv">base</span><span class="o">=</span><span class="k">$(</span>basename<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$file</span><span class="s2">&quot;</span><span class="k">)</span>
|
||
<span class="nv">title</span><span class="o">=</span><span class="s2">&quot;</span><span class="nv">$base</span><span class="s2">&quot;</span>
|
||
<span class="nv">visibility</span><span class="o">=</span><span class="s2">&quot;public&quot;</span>
|
||
|
||
<span class="c1"># Use `cat` to fetch the content of the file</span>
|
||
<span class="nv">content</span><span class="o">=</span><span class="k">$(</span>cat<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$file</span><span class="s2">&quot;</span><span class="k">)</span>
|
||
|
||
<span class="nv">result</span><span class="o">=</span><span class="k">$(</span>gitlab<span class="w"> </span>snippet<span class="w"> </span>create<span class="w"> </span>--title<span class="o">=</span><span class="s2">&quot;</span><span class="nv">$title</span><span class="s2">&quot;</span><span class="w"> </span>--file-name<span class="o">=</span><span class="s2">&quot;</span><span class="nv">$title</span><span class="s2">&quot;</span><span class="w"> </span>--content<span class="o">=</span><span class="s2">&quot;</span><span class="nv">$content</span><span class="s2">&quot;</span><span class="w"> </span>--visibility<span class="o">=</span><span class="s2">&quot;</span><span class="nv">$visibility</span><span class="s2">&quot;</span><span class="k">)</span>
|
||
|
||
<span class="nv">id</span><span class="o">=</span><span class="k">$(</span><span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;</span><span class="nv">$result</span><span class="s2">&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>awk<span class="w"> </span><span class="s1">&#39;/id: / { print $2 }&#39;</span><span class="k">)</span>
|
||
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;https://gitlab.com/-/snippets/</span><span class="nv">$id</span><span class="s2">&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>I can now do <code>snip README.md</code> and that will create the snippet for me&nbsp;:-)</p></content><category term="code"></category></entry><entry><title>Creating an online space to share markdown files</title><link href="https://blog.notmyidea.org/creating-an-online-space-to-share-markdown-files.html" rel="alternate"></link><published>2023-09-17T00:00:00+02:00</published><updated>2023-09-17T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-17:/creating-an-online-space-to-share-markdown-files.html</id><summary type="html">
|
||
<p>I wanted to create a space on my server where I can upload markdown files and have them rendered directly, for them to be shared with other&nbsp;people.</p>
|
||
<p>I stumbled on <a href="https://github.com/ukarim/ngx_markdown_filter_module">the markdown module for nginx</a> which does exactly what I want, but seemed to ask for compilation of nginx …</p></summary><content type="html">
|
||
<p>I wanted to create a space on my server where I can upload markdown files and have them rendered directly, for them to be shared with other&nbsp;people.</p>
|
||
<p>I stumbled on <a href="https://github.com/ukarim/ngx_markdown_filter_module">the markdown module for nginx</a> which does exactly what I want, but seemed to ask for compilation of nginx, which wasn&#8217;t exactly what I wanted in terms of maintainability (it would make it complicated to update&nbsp;it)</p>
|
||
<p>I then thought that the <a href="https://caddyserver.com/">Caddy</a> server does that by default, and so I&#8217;ve tested it out. Turns out it&#8217;s not, but it offers ways to do this thanks to its template&nbsp;mecanism.</p>
|
||
<p>It also, <a href="https://caddyserver.com/docs/automatic-https">setups automatically and transparently <span class="caps">SSL</span> certificates</a> for you (using Let&#8217;s Encrypt!), so I wanted to have a&nbsp;look.</p>
|
||
<p>Here is the Caddy configuration file I&#8217;m now using&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>md.notmyidea.org {
|
||
root <span class="gs">* /home/caddy/md.notmyidea.org</span>
|
||
<span class="gs"> rewrite *</span> /index.html
|
||
file_server
|
||
templates
|
||
encode zstd gzip
|
||
|
||
}
|
||
</code></pre></div>
|
||
|
||
<p>And the&nbsp;template:</p>
|
||
<div class="highlight"><pre><span></span><code>{{$pathParts := splitList &quot;/&quot; .OriginalReq.URL.Path}}
|
||
{{$markdownFilename := default &quot;index&quot; (slice $pathParts 1 | join &quot;/&quot;)}}
|
||
|
||
{{if not (fileExists $markdownFilename)}}
|
||
{{httpError 404}}
|
||
{{end}}
|
||
|
||
{{$markdownFile := (include $markdownFilename | splitFrontMatter)}}
|
||
<span class="cp">&lt;!DOCTYPE html&gt;</span>
|
||
<span class="p">&lt;</span><span class="nt">html</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;</span><span class="nt">head</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span>{{ $markdownFilename }}<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;/</span><span class="nt">head</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span>
|
||
{{ markdown $markdownFile.Body }}
|
||
<span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span>
|
||
<span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span>
|
||
</code></pre></div>
|
||
|
||
<p>This is a minimalistic version, but it works&nbsp;:-)</p></content><category term="code"></category></entry><entry><title>Conversion d’un fichier svg en favicon.ico</title><link href="https://blog.notmyidea.org/conversion-dun-fichier-svg-en-faviconico.html" rel="alternate"></link><published>2023-09-13T00:00:00+02:00</published><updated>2023-09-13T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-13:/conversion-dun-fichier-svg-en-faviconico.html</id><summary type="html">
|
||
<p>Il y a plusieurs sites qui permettent de faire ça automatiquement, mais j&#8217;aime bien faire les choses depuis mon terminal, voici donc une commande qui permet de faire ça simplement, en utilisant <a href="https://imagemagick.org/">ImageMagick</a>. Merci à <a href="https://gist.github.com/azam/3b6995a29b9f079282f3">ce&nbsp;gist</a></p>
|
||
<div class="highlight"><pre><span></span><code>convert<span class="w"> </span>-density<span class="w"> </span>256x256<span class="w"> </span>-background<span class="w"> </span>transparent<span class="w"> </span>favicon.svg<span class="w"> </span>-define<span class="w"> </span>icon:auto-resize<span class="w"> </span>-colors<span class="w"> </span><span class="m">256 …</span></code></pre></div></summary><content type="html">
|
||
<p>Il y a plusieurs sites qui permettent de faire ça automatiquement, mais j&#8217;aime bien faire les choses depuis mon terminal, voici donc une commande qui permet de faire ça simplement, en utilisant <a href="https://imagemagick.org/">ImageMagick</a>. Merci à <a href="https://gist.github.com/azam/3b6995a29b9f079282f3">ce&nbsp;gist</a></p>
|
||
<div class="highlight"><pre><span></span><code>convert<span class="w"> </span>-density<span class="w"> </span>256x256<span class="w"> </span>-background<span class="w"> </span>transparent<span class="w"> </span>favicon.svg<span class="w"> </span>-define<span class="w"> </span>icon:auto-resize<span class="w"> </span>-colors<span class="w"> </span><span class="m">256</span><span class="w"> </span>favicon.ico
|
||
</code></pre></div></content><category term="code"></category></entry><entry><title>Découverte de nouveaux outils pour le développement: LLM, Helix et plus</title><link href="https://blog.notmyidea.org/decouverte-de-nouveaux-outils-pour-le-developpement-llm-helix-et-plus.html" rel="alternate"></link><published>2023-09-12T00:00:00+02:00</published><updated>2023-09-12T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-09-12:/decouverte-de-nouveaux-outils-pour-le-developpement-llm-helix-et-plus.html</id><summary type="html">
|
||
<h2 id="llm"><span class="caps">LLM</span></h2>
|
||
<ul>
|
||
<li><a href="https://localai.io/model-compatibility/">LocalAI</a> permet de faire tourner des modèles en local avec la même <span class="caps">API</span> <span class="caps">HTTP</span> que celle&nbsp;d&#8217;OpenAI</li>
|
||
<li><a href="https://github.com/bofenghuang/vigogne">Le modèle Vigogne</a> est un modèle entrainé (<em>fine-tuned</em>) avec des données en Français. Notamment <a href="https://huggingface.co/bofenghuang/vigogne-2-7b-chat/tree/v1.0">ce modèle</a>qui prends <span class="caps">LLAMA2</span> en&nbsp;entrée.</li>
|
||
<li><a href="https://python.langchain.com/docs/get_started/introduction.html">LangChain</a> semble être un framework pour travailler avec les différents …</li></ul></summary><content type="html">
|
||
<h2 id="llm"><span class="caps">LLM</span></h2>
|
||
<ul>
|
||
<li><a href="https://localai.io/model-compatibility/">LocalAI</a> permet de faire tourner des modèles en local avec la même <span class="caps">API</span> <span class="caps">HTTP</span> que celle&nbsp;d&#8217;OpenAI</li>
|
||
<li><a href="https://github.com/bofenghuang/vigogne">Le modèle Vigogne</a> est un modèle entrainé (<em>fine-tuned</em>) avec des données en Français. Notamment <a href="https://huggingface.co/bofenghuang/vigogne-2-7b-chat/tree/v1.0">ce modèle</a>qui prends <span class="caps">LLAMA2</span> en&nbsp;entrée.</li>
|
||
<li><a href="https://python.langchain.com/docs/get_started/introduction.html">LangChain</a> semble être un framework pour travailler avec les différents concepts utiles. A&nbsp;voir.</li>
|
||
</ul>
|
||
<p>Pour la première fois, j&#8217;ai commencé à utiliser un peu plus l&#8217;outil <a href="https://llm.datasette.io">llm</a> pour m&#8217;aider dans les tâches de&nbsp;programmation. </p>
|
||
<p>!! warning
|
||
J&#8217;utilise actuellement par défaut le modèle en ligne d&#8217;OpenAI &#8220;<span class="caps">GTP4</span>&#8221;, à travers leur <span class="caps">API</span>. Cela me pose des problèmes éthiques, mais mon approche est pour le moment de voir le type de résultats que j&#8217;obtiens pour ensuite comparer avec des modèles locaux type <span class="caps">LLAMA2</span>.</p>
|
||
<p>Deux choses que j&#8217;ai trouvées utiles&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>git<span class="w"> </span>diff<span class="w"> </span><span class="p">|</span><span class="w"> </span>llm<span class="w"> </span><span class="s2">&quot;write me a commit message&quot;</span>
|
||
git<span class="w"> </span>diff<span class="w"> </span><span class="p">|</span><span class="w"> </span>llm<span class="w"> </span><span class="s2">&quot;find a branch name&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>Qui peuvent faciliter la vie plutôt que de chercher à décrire des choses manuellement (le &#8220;branch-name&#8221;, je le trouve particulièrement&nbsp;utile)</p>
|
||
<p>J&#8217;ai aussi trouvé l&#8217;idée intéressante d&#8217;automatiser l&#8217;écrite de tests, avec pytest. Bien sur ça ne fait pas tout, mais ça donne un template de départ qui est intéressant&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>cat<span class="w"> </span>code/test_file.py<span class="w"> </span><span class="p">|</span><span class="w"> </span>llm<span class="w"> </span><span class="s2">&quot;write tests for this, using pytest&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>J&#8217;ai par exemple demandé à llm de me lister 20 titres pour cet article&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>cat<span class="w"> </span>~/dev/til.notmyidea.org/content/<span class="k">$(</span>date<span class="w"> </span>+%F<span class="k">)</span>.md<span class="w"> </span><span class="p">|</span><span class="w"> </span>llm<span class="w"> </span><span class="s2">&quot;Liste moi 20 titres pour cet article. Quelque chose de simple&quot;</span>
|
||
<span class="m">1</span>.<span class="w"> </span><span class="s2">&quot;Découverte de nouveaux outils pour le développement: LLM, Helix et plus&quot;</span>
|
||
<span class="m">2</span>.<span class="w"> </span><span class="s2">&quot;Explorer les modèles LLM pour la génération de code&quot;</span>
|
||
<span class="m">3</span>.<span class="w"> </span><span class="s2">&quot;L&#39;amélioration du développement grâce à LLM et Helix&quot;</span>
|
||
<span class="m">4</span>.<span class="w"> </span><span class="s2">&quot;Introduction à l&#39;éditeur Helix et à LLM&quot;</span>
|
||
<span class="m">5</span>.<span class="w"> </span><span class="s2">&quot;Boostez votre productivité de développement avec LLM et Helix&quot;</span>
|
||
<span class="m">6</span>.<span class="w"> </span><span class="s2">&quot;Comment j&#39;intègre LLM et Helix dans mon flux de travail de développement&quot;</span>
|
||
<span class="m">7</span>.<span class="w"> </span><span class="s2">&quot;Les avantages de l&#39;utilisation de LLM pour la programmation&quot;</span>
|
||
<span class="m">8</span>.<span class="w"> </span><span class="s2">&quot;Approches innovantes pour le développement de code avec LLM&quot;</span>
|
||
<span class="m">9</span>.<span class="w"> </span><span class="s2">&quot;L&#39;avenir du développement de code avec LLM et Helix&quot;</span>
|
||
<span class="m">10</span>.<span class="w"> </span><span class="s2">&quot;Optimisation des tâches de programmation avec LLM&quot;</span>
|
||
<span class="m">11</span>.<span class="w"> </span><span class="s2">&quot;Ouvrir de nouvelles possibilités de codage avec LLM et Helix&quot;</span>
|
||
<span class="m">12</span>.<span class="w"> </span><span class="s2">&quot;Utiliser des modèles LLM pour améliorer la qualité du code&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="helix">Helix</h2>
|
||
<p>Je me mets à tester un peu plus l&#8217;éditeur Helix. Je suis un habitué de Vim pour toutes les petites modifications que je fais depuis mon terminal, et Helix semble&nbsp;intéressant.</p>
|
||
<ul>
|
||
<li><code>x</code>pour sélectionner une ligne (<code>xd</code> pour sélectionner et&nbsp;supprimer)</li>
|
||
<li><code>ma</code> pour sélectionner &#8220;around&#8221; quelque chose. <code>maw</code> pour sélectionner le&nbsp;mot</li>
|
||
<li><code>c</code> pour effacer la sélection et passer en mode&nbsp;insertion.</li>
|
||
</ul>
|
||
<h2 id="divers">Divers</h2>
|
||
<blockquote>
|
||
<p>J’ai fait confiance, j’ai appris.
|
||
— <a href="https://d%C3%A9tour.studio">Thomas</a></p>
|
||
</blockquote>
|
||
<p>J&#8217;aime beaucoup ce que ça dit. Faire confiance est peut-être nécessaire, même si on est déçu au final, on aura au moins appris. Ça me&nbsp;touche.</p></content><category term="code"></category></entry><entry><title>Running the Gitlab CI locally</title><link href="https://blog.notmyidea.org/running-the-gitlab-ci-locally.html" rel="alternate"></link><published>2023-08-19T00:00:00+02:00</published><updated>2023-08-19T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-08-19:/running-the-gitlab-ci-locally.html</id><summary type="html">
|
||
<p>Sometimes, I need to change how the continuous integration is setup, and I find
|
||
myself pushing to a branch to test if my changes are working. Oftentimes, it
|
||
takes me multiple commits to find the correct configuration, which is…&nbsp;suboptimal.</p>
|
||
<p>I discovered today <a href="https://github.com/firecow/gitlab-ci-local">Gitlab <span class="caps">CI</span>
|
||
local</a> which makes it possible …</p></summary><content type="html">
|
||
<p>Sometimes, I need to change how the continuous integration is setup, and I find
|
||
myself pushing to a branch to test if my changes are working. Oftentimes, it
|
||
takes me multiple commits to find the correct configuration, which is…&nbsp;suboptimal.</p>
|
||
<p>I discovered today <a href="https://github.com/firecow/gitlab-ci-local">Gitlab <span class="caps">CI</span>
|
||
local</a> which makes it possible to
|
||
run the <span class="caps">CI</span> actions locally, without having to push to the remote <span class="caps">CI</span>. The same
|
||
thing exists for <a href="https://github.com/nektos/act">Microsoft Github</a>.</p>
|
||
<p>Under the hood, it&#8217;s using Docker, so you need to have it running on your
|
||
system, but once it&#8217;s done, you just have to issue a simple command to see the
|
||
results. Very helpful&nbsp;:-)</p>
|
||
<p>Here is an example&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>gitlab-ci-local<span class="w"> </span><span class="nb">test</span>
|
||
parsing<span class="w"> </span>and<span class="w"> </span>downloads<span class="w"> </span>finished<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">41</span><span class="w"> </span>ms
|
||
<span class="nb">test</span><span class="w"> </span>starting<span class="w"> </span>python:3.8-alpine<span class="w"> </span><span class="o">(</span><span class="nb">test</span><span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>copied<span class="w"> </span>to<span class="w"> </span>docker<span class="w"> </span>volumes<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">4</span>.05<span class="w"> </span>s
|
||
<span class="nb">test</span><span class="w"> </span>$<span class="w"> </span>apk<span class="w"> </span>update<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>apk<span class="w"> </span>add<span class="w"> </span>make<span class="w"> </span>libsass<span class="w"> </span>gcc<span class="w"> </span>musl-dev<span class="w"> </span>g++
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>fetch<span class="w"> </span>https://dl-cdn.alpinelinux.org/alpine/v3.18/main/aarch64/APKINDEX.tar.gz
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>fetch<span class="w"> </span>https://dl-cdn.alpinelinux.org/alpine/v3.18/community/aarch64/APKINDEX.tar.gz
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>v3.18.3-55-g2ee93b9273a<span class="w"> </span><span class="o">[</span>https://dl-cdn.alpinelinux.org/alpine/v3.18/main<span class="o">]</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>v3.18.3-56-g4a3b0382caa<span class="w"> </span><span class="o">[</span>https://dl-cdn.alpinelinux.org/alpine/v3.18/community<span class="o">]</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>OK:<span class="w"> </span><span class="m">19939</span><span class="w"> </span>distinct<span class="w"> </span>packages<span class="w"> </span>available
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">1</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libgcc<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">2</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libstdc++<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">3</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libstdc++-dev<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">4</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>zstd-libs<span class="w"> </span><span class="o">(</span><span class="m">1</span>.5.5-r4<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">5</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>binutils<span class="w"> </span><span class="o">(</span><span class="m">2</span>.40-r7<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">6</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libgomp<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">7</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libatomic<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">8</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>gmp<span class="w"> </span><span class="o">(</span><span class="m">6</span>.2.1-r3<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">9</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>isl26<span class="w"> </span><span class="o">(</span><span class="m">0</span>.26-r1<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">10</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>mpfr4<span class="w"> </span><span class="o">(</span><span class="m">4</span>.2.0_p12-r0<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">11</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>mpc1<span class="w"> </span><span class="o">(</span><span class="m">1</span>.3.1-r1<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">12</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>gcc<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">13</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>musl-dev<span class="w"> </span><span class="o">(</span><span class="m">1</span>.2.4-r1<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">14</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libc-dev<span class="w"> </span><span class="o">(</span><span class="m">0</span>.7.2-r5<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">15</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>g++<span class="w"> </span><span class="o">(</span><span class="m">12</span>.2.1_git20220924-r10<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">16</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>libsass<span class="w"> </span><span class="o">(</span><span class="m">3</span>.6.5-r0<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">(</span><span class="m">17</span>/17<span class="o">)</span><span class="w"> </span>Installing<span class="w"> </span>make<span class="w"> </span><span class="o">(</span><span class="m">4</span>.4.1-r1<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Executing<span class="w"> </span>busybox-1.36.1-r2.trigger
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>OK:<span class="w"> </span><span class="m">246</span><span class="w"> </span>MiB<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">55</span><span class="w"> </span>packages
|
||
<span class="nb">test</span><span class="w"> </span>$<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>-r<span class="w"> </span>requirements.txt
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>pelican
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>pelican-4.8.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">1</span>.4<span class="w"> </span>MB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">1</span>.4/1.4<span class="w"> </span>MB<span class="w"> </span><span class="m">539</span>.9<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>markdown
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>Markdown-3.4.4-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">94</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">94</span>.2/94.2<span class="w"> </span>kB<span class="w"> </span><span class="m">540</span>.1<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>typogrify
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>typogrify-2.0.7.tar.gz<span class="w"> </span><span class="o">(</span><span class="m">12</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Preparing<span class="w"> </span>metadata<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>started
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Preparing<span class="w"> </span>metadata<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>finished<span class="w"> </span>with<span class="w"> </span>status<span class="w"> </span><span class="s1">&#39;done&#39;</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>pelican-search
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>pelican_search-1.1.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">6</span>.6<span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>pelican-neighbors
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>pelican_neighbors-1.2.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">16</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>pelican-webassets
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>pelican_webassets-2.0.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">5</span>.8<span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>libsass
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>libsass-0.22.0.tar.gz<span class="w"> </span><span class="o">(</span><span class="m">316</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">316</span>.3/316.3<span class="w"> </span>kB<span class="w"> </span><span class="m">552</span>.1<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Preparing<span class="w"> </span>metadata<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>started
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Preparing<span class="w"> </span>metadata<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>finished<span class="w"> </span>with<span class="w"> </span>status<span class="w"> </span><span class="s1">&#39;done&#39;</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>docutils&gt;<span class="o">=</span><span class="m">0</span>.16
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>docutils-0.20.1-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">572</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">572</span>.7/572.7<span class="w"> </span>kB<span class="w"> </span><span class="m">549</span>.2<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>rich&gt;<span class="o">=</span><span class="m">10</span>.1
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>rich-13.5.2-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">239</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">239</span>.7/239.7<span class="w"> </span>kB<span class="w"> </span><span class="m">485</span>.3<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>jinja2&gt;<span class="o">=</span><span class="m">2</span>.7
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>Jinja2-3.1.2-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">133</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">133</span>.1/133.1<span class="w"> </span>kB<span class="w"> </span><span class="m">342</span>.6<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>pytz&gt;<span class="o">=</span><span class="m">2020</span>.1
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>pytz-2023.3-py2.py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">502</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">502</span>.3/502.3<span class="w"> </span>kB<span class="w"> </span><span class="m">547</span>.3<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>pygments&gt;<span class="o">=</span><span class="m">2</span>.6
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>Pygments-2.16.1-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">1</span>.2<span class="w"> </span>MB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">1</span>.2/1.2<span class="w"> </span>MB<span class="w"> </span><span class="m">551</span>.4<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>unidecode&gt;<span class="o">=</span><span class="m">1</span>.1
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>Unidecode-1.3.6-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">235</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">235</span>.9/235.9<span class="w"> </span>kB<span class="w"> </span><span class="m">554</span>.2<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>blinker&gt;<span class="o">=</span><span class="m">1</span>.4
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>blinker-1.6.2-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">13</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>python-dateutil&gt;<span class="o">=</span><span class="m">2</span>.8
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>python_dateutil-2.8.2-py2.py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">247</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">247</span>.7/247.7<span class="w"> </span>kB<span class="w"> </span><span class="m">235</span>.7<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>feedgenerator&gt;<span class="o">=</span><span class="m">1</span>.9
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>feedgenerator-2.1.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">21</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>importlib-metadata&gt;<span class="o">=</span><span class="m">4</span>.4
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>importlib_metadata-6.8.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">22</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>smartypants&gt;<span class="o">=</span><span class="m">1</span>.8.3
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>smartypants-2.0.1-py2.py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">9</span>.9<span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>rtoml&lt;<span class="m">0</span>.10.0,&gt;<span class="o">=</span><span class="m">0</span>.9.0
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>rtoml-0.9.0-cp38-cp38-musllinux_1_1_aarch64.whl<span class="w"> </span><span class="o">(</span><span class="m">846</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">846</span>.2/846.2<span class="w"> </span>kB<span class="w"> </span><span class="m">503</span>.7<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>webassets&lt;<span class="m">3</span>.0,&gt;<span class="o">=</span><span class="m">2</span>.0
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>webassets-2.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">142</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">142</span>.9/142.9<span class="w"> </span>kB<span class="w"> </span><span class="m">551</span>.8<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>zipp&gt;<span class="o">=</span><span class="m">0</span>.5
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>zipp-3.16.2-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">7</span>.2<span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>MarkupSafe&gt;<span class="o">=</span><span class="m">2</span>.0
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl<span class="w"> </span><span class="o">(</span><span class="m">30</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>six&gt;<span class="o">=</span><span class="m">1</span>.5
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>six-1.16.0-py2.py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">11</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>markdown-it-py&gt;<span class="o">=</span><span class="m">2</span>.2.0
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>markdown_it_py-3.0.0-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">87</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━<span class="w"> </span><span class="m">87</span>.5/87.5<span class="w"> </span>kB<span class="w"> </span><span class="m">561</span>.7<span class="w"> </span>kB/s<span class="w"> </span>eta<span class="w"> </span><span class="m">0</span>:00:00
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>typing-extensions&lt;<span class="m">5</span>.0,&gt;<span class="o">=</span><span class="m">4</span>.0.0
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>typing_extensions-4.7.1-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">33</span><span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Collecting<span class="w"> </span>mdurl~<span class="o">=</span><span class="m">0</span>.1
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Downloading<span class="w"> </span>mdurl-0.1.2-py3-none-any.whl<span class="w"> </span><span class="o">(</span><span class="m">10</span>.0<span class="w"> </span>kB<span class="o">)</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Building<span class="w"> </span>wheels<span class="w"> </span><span class="k">for</span><span class="w"> </span>collected<span class="w"> </span>packages:<span class="w"> </span>typogrify,<span class="w"> </span>libsass
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Building<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>typogrify<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>started
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Building<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>typogrify<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>finished<span class="w"> </span>with<span class="w"> </span>status<span class="w"> </span><span class="s1">&#39;done&#39;</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Created<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>typogrify:<span class="w"> </span><span class="nv">filename</span><span class="o">=</span>typogrify-2.0.7-py2.py3-none-any.whl<span class="w"> </span><span class="nv">size</span><span class="o">=</span><span class="m">13452</span><span class="w"> </span><span class="nv">sha256</span><span class="o">=</span>4ce329903e807671102eab7fd2bc49765b6efc3a4ae68c82053318b62789083c
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Stored<span class="w"> </span><span class="k">in</span><span class="w"> </span>directory:<span class="w"> </span>/root/.cache/pip/wheels/0b/e9/98/c888501e8dd2166da059e4f8418694de9b50b48a7192712be9
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Building<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>libsass<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>started
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Building<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>libsass<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>still<span class="w"> </span>running...
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Building<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>libsass<span class="w"> </span><span class="o">(</span>setup.py<span class="o">)</span>:<span class="w"> </span>finished<span class="w"> </span>with<span class="w"> </span>status<span class="w"> </span><span class="s1">&#39;done&#39;</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Created<span class="w"> </span>wheel<span class="w"> </span><span class="k">for</span><span class="w"> </span>libsass:<span class="w"> </span><span class="nv">filename</span><span class="o">=</span>libsass-0.22.0-cp38-abi3-linux_aarch64.whl<span class="w"> </span><span class="nv">size</span><span class="o">=</span><span class="m">13710320</span><span class="w"> </span><span class="nv">sha256</span><span class="o">=</span>3dcb4ce97c1aafc179a6343e0f312c17df88e56c4eb647ab54b09ead5ee00b92
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Stored<span class="w"> </span><span class="k">in</span><span class="w"> </span>directory:<span class="w"> </span>/root/.cache/pip/wheels/95/64/fa/47638d5037df216387cdc168e9871d5d9851fc995d636bd108
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Successfully<span class="w"> </span>built<span class="w"> </span>typogrify<span class="w"> </span>libsass
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Installing<span class="w"> </span>collected<span class="w"> </span>packages:<span class="w"> </span>webassets,<span class="w"> </span>smartypants,<span class="w"> </span>pytz,<span class="w"> </span>zipp,<span class="w"> </span>unidecode,<span class="w"> </span>typogrify,<span class="w"> </span>typing-extensions,<span class="w"> </span>six,<span class="w"> </span>rtoml,<span class="w"> </span>pygments,<span class="w"> </span>mdurl,<span class="w"> </span>MarkupSafe,<span class="w"> </span>libsass,<span class="w"> </span>feedgenerator,<span class="w"> </span>docutils,<span class="w"> </span>blinker,<span class="w"> </span>python-dateutil,<span class="w"> </span>markdown-it-py,<span class="w"> </span>jinja2,<span class="w"> </span>importlib-metadata,<span class="w"> </span>rich,<span class="w"> </span>markdown,<span class="w"> </span>pelican,<span class="w"> </span>pelican-webassets,<span class="w"> </span>pelican-search,<span class="w"> </span>pelican-neighbors
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Successfully<span class="w"> </span>installed<span class="w"> </span>MarkupSafe-2.1.3<span class="w"> </span>blinker-1.6.2<span class="w"> </span>docutils-0.20.1<span class="w"> </span>feedgenerator-2.1.0<span class="w"> </span>importlib-metadata-6.8.0<span class="w"> </span>jinja2-3.1.2<span class="w"> </span>libsass-0.22.0<span class="w"> </span>markdown-3.4.4<span class="w"> </span>markdown-it-py-3.0.0<span class="w"> </span>mdurl-0.1.2<span class="w"> </span>pelican-4.8.0<span class="w"> </span>pelican-neighbors-1.2.0<span class="w"> </span>pelican-search-1.1.0<span class="w"> </span>pelican-webassets-2.0.0<span class="w"> </span>pygments-2.16.1<span class="w"> </span>python-dateutil-2.8.2<span class="w"> </span>pytz-2023.3<span class="w"> </span>rich-13.5.2<span class="w"> </span>rtoml-0.9.0<span class="w"> </span>six-1.16.0<span class="w"> </span>smartypants-2.0.1<span class="w"> </span>typing-extensions-4.7.1<span class="w"> </span>typogrify-2.0.7<span class="w"> </span>unidecode-1.3.6<span class="w"> </span>webassets-2.0<span class="w"> </span>zipp-3.16.2
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>WARNING:<span class="w"> </span>Running<span class="w"> </span>pip<span class="w"> </span>as<span class="w"> </span>the<span class="w"> </span><span class="s1">&#39;root&#39;</span><span class="w"> </span>user<span class="w"> </span>can<span class="w"> </span>result<span class="w"> </span><span class="k">in</span><span class="w"> </span>broken<span class="w"> </span>permissions<span class="w"> </span>and<span class="w"> </span>conflicting<span class="w"> </span>behaviour<span class="w"> </span>with<span class="w"> </span>the<span class="w"> </span>system<span class="w"> </span>package<span class="w"> </span>manager.<span class="w"> </span>It<span class="w"> </span>is<span class="w"> </span>recommended<span class="w"> </span>to<span class="w"> </span>use<span class="w"> </span>a<span class="w"> </span>virtual<span class="w"> </span>environment<span class="w"> </span>instead:<span class="w"> </span>https://pip.pypa.io/warnings/venv
|
||
<span class="nb">test</span><span class="w"> </span>&gt;
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">[</span>notice<span class="o">]</span><span class="w"> </span>A<span class="w"> </span>new<span class="w"> </span>release<span class="w"> </span>of<span class="w"> </span>pip<span class="w"> </span>is<span class="w"> </span>available:<span class="w"> </span><span class="m">23</span>.0.1<span class="w"> </span>-&gt;<span class="w"> </span><span class="m">23</span>.2.1
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="o">[</span>notice<span class="o">]</span><span class="w"> </span>To<span class="w"> </span>update,<span class="w"> </span>run:<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>--upgrade<span class="w"> </span>pip
|
||
<span class="nb">test</span><span class="w"> </span>$<span class="w"> </span>make<span class="w"> </span>publish
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span><span class="s2">&quot;pelican&quot;</span><span class="w"> </span><span class="s2">&quot;/gcl-builds/content&quot;</span><span class="w"> </span>-o<span class="w"> </span><span class="s2">&quot;/gcl-builds/public&quot;</span><span class="w"> </span>-s<span class="w"> </span><span class="s2">&quot;/gcl-builds/publishconf.py&quot;</span>
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>Done:<span class="w"> </span>Processed<span class="w"> </span><span class="m">5</span><span class="w"> </span>articles,<span class="w"> </span><span class="m">0</span><span class="w"> </span>drafts,<span class="w"> </span><span class="m">0</span><span class="w"> </span>hidden<span class="w"> </span>articles,<span class="w"> </span><span class="m">2</span><span class="w"> </span>pages,<span class="w"> </span><span class="m">0</span><span class="w"> </span>hidden<span class="w"> </span>pages
|
||
<span class="nb">test</span><span class="w"> </span>&gt;<span class="w"> </span>and<span class="w"> </span><span class="m">0</span><span class="w"> </span>draft<span class="w"> </span>pages<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">0</span>.50<span class="w"> </span>seconds.
|
||
<span class="nb">test</span><span class="w"> </span>finished<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="m">6</span><span class="w"> </span>min
|
||
PASS<span class="w"> </span><span class="nb">test</span>
|
||
</code></pre></div></content><category term="code"></category><category term="gitlab"></category><category term="docker"></category></entry><entry><title>ArchLinux et mise à jour du keyring</title><link href="https://blog.notmyidea.org/archlinux-et-mise-a-jour-du-keyring.html" rel="alternate"></link><published>2023-08-18T00:00:00+02:00</published><updated>2023-08-18T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-08-18:/archlinux-et-mise-a-jour-du-keyring.html</id><summary type="html">
|
||
<p>Pour les mises à jour Arch, j&#8217;utilise <a href="https://github.com/Jguer/yay">yay</a>. Je
|
||
ne fais les mises à jour que de manière semi-régulière, et parfois après une
|
||
longue période je me retrouve avec des soucis de clé qui ne sont plus à jour ou&nbsp;manquantes.</p>
|
||
<p>Avec une utilisation fréquente du système, aucun problème …</p></summary><content type="html">
|
||
<p>Pour les mises à jour Arch, j&#8217;utilise <a href="https://github.com/Jguer/yay">yay</a>. Je
|
||
ne fais les mises à jour que de manière semi-régulière, et parfois après une
|
||
longue période je me retrouve avec des soucis de clé qui ne sont plus à jour ou&nbsp;manquantes.</p>
|
||
<p>Avec une utilisation fréquente du système, aucun problème ne se pose car un
|
||
service s&#8217;occupe de faire la mise à jour des clés de manière&nbsp;automatique.</p>
|
||
<p>Pour résoudre le souci, il suffit de mettre à jour le paquet
|
||
<code>archlinux-keyring</code>, comme décrit <a href="https://wiki.archlinux.org/title/Pacman/Package_signing">dans la page Wiki qui va
|
||
bien</a>.</p>
|
||
<div class="highlight"><pre><span></span><code>sudo pacman -S archlinux-keyring
|
||
</code></pre></div></content><category term="code"></category><category term="arch-linux"></category></entry><entry><title>Python packaging with Hatch, pipx and Zsh environment variables</title><link href="https://blog.notmyidea.org/python-packaging-with-hatch-pipx-and-zsh-environment-variables.html" rel="alternate"></link><published>2023-08-17T00:00:00+02:00</published><updated>2023-08-17T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-08-17:/python-packaging-with-hatch-pipx-and-zsh-environment-variables.html</id><summary type="html">
|
||
<p>It&#8217;s been a while I didn&#8217;t packaged something new. I recently remembered an old
|
||
package of mine that needed some attention :
|
||
<a href="https://gitlab.com/almet/debts">debts</a>. It&#8217;s now time to package it, so I
|
||
discovered <a href="https://hatch.pypa.io/">hatch</a></p>
|
||
<p>hatch new&nbsp;&#8212;init</p>
|
||
<p>This does the heavy-lifting for you, actually porting the <code>setup.py</code> files …</p></summary><content type="html">
|
||
<p>It&#8217;s been a while I didn&#8217;t packaged something new. I recently remembered an old
|
||
package of mine that needed some attention :
|
||
<a href="https://gitlab.com/almet/debts">debts</a>. It&#8217;s now time to package it, so I
|
||
discovered <a href="https://hatch.pypa.io/">hatch</a></p>
|
||
<p>hatch new&nbsp;&#8212;init</p>
|
||
<p>This does the heavy-lifting for you, actually porting the <code>setup.py</code> files to the
|
||
new way of packaging with python (with a <code>pyproject.toml</code> file)</p>
|
||
<p>Then <code>hatch shell</code> will create a development environment, install dependencies,
|
||
check the <code>pyproject.toml</code> file in one command, and give you a shell to test
|
||
whatever you need to&nbsp;test.</p>
|
||
<h2 id="isolating-system-packages">Isolating system&nbsp;packages</h2>
|
||
<p>I discovered that <a href="https://github.com/pypa/pipx">pipx</a> is a convenient way to
|
||
install user-facing applications on my system. I use multiple virtual
|
||
environments for my different projects, but not for the install that are used&nbsp;system-wide.</p>
|
||
<p>pipx seems to solve this, and avoid using <code>sudo pip install x</code>.</p>
|
||
<h2 id="manipulating-env-variables-with-zsh">Manipulating env variables with&nbsp;Zsh</h2>
|
||
<p>I use <a href="https://www.zsh.org/">Zsh</a> as my main shell for years, and I just
|
||
discovered that it&#8217;s possible to manipulate environment variables in an easy&nbsp;way.</p>
|
||
<p>If you&#8217;re like me, you never remember how to add something to your path. You
|
||
can actually use <code>+=</code>, like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nv">path</span><span class="o">+=(</span><span class="s1">&#39;/Users/alexis/.local/bin&#39;</span><span class="o">)</span>
|
||
<span class="nb">export</span><span class="w"> </span>PATH
|
||
</code></pre></div></content><category term="code"></category><category term="python"></category><category term="packaging"></category><category term="zsh"></category></entry><entry><title>Profiling and speeding up Django and Pytest</title><link href="https://blog.notmyidea.org/profiling-and-speeding-up-django-and-pytest.html" rel="alternate"></link><published>2023-08-16T00:00:00+02:00</published><updated>2023-08-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-08-16:/profiling-and-speeding-up-django-and-pytest.html</id><summary type="html">
|
||
<p><a href="https://yaal.coop/">Éloi</a> made <a href="https://github.com/spiral-project/ihatemoney/issues/1214">a pull request on
|
||
IHateMoney</a> to
|
||
speedup the tests, with some great tooling for pytest that I wasn&#8217;t aware&nbsp;of:</p>
|
||
<ul>
|
||
<li><a href="https://pypi.org/project/pytest-xdist/">pytest-xdist</a> allows to run tests in
|
||
parallel, using <code>-n auto</code></li>
|
||
<li><a href="https://pypi.org/project/pytest-profiling/">pytest-profiling</a> makes it easy
|
||
to get the call stack and time the function calls that take most …</li></ul></summary><content type="html">
|
||
<p><a href="https://yaal.coop/">Éloi</a> made <a href="https://github.com/spiral-project/ihatemoney/issues/1214">a pull request on
|
||
IHateMoney</a> to
|
||
speedup the tests, with some great tooling for pytest that I wasn&#8217;t aware&nbsp;of:</p>
|
||
<ul>
|
||
<li><a href="https://pypi.org/project/pytest-xdist/">pytest-xdist</a> allows to run tests in
|
||
parallel, using <code>-n auto</code></li>
|
||
<li><a href="https://pypi.org/project/pytest-profiling/">pytest-profiling</a> makes it easy
|
||
to get the call stack and time the function calls that take most of the&nbsp;time.</li>
|
||
<li>You can them analyse the <code>.prof</code> files with
|
||
<a href="https://pypi.org/project/snakeviz/">Snakeviz</a></li>
|
||
</ul>
|
||
<p>So, I spent some time using these on the tests for <a href="https://chariotte.fr">La
|
||
Chariotte</a>, because they were&nbsp;slow.</p>
|
||
<p>I found two things&nbsp;:</p>
|
||
<ul>
|
||
<li>Login calls are costly in the test, and it&#8217;s possible to speed things up&nbsp;;</li>
|
||
<li>On my machine, calls to resolve my hostname were slow, using 5s during the
|
||
tests for a lookup that wasn&#8217;t even&nbsp;useful.</li>
|
||
</ul>
|
||
<h2 id="changing-the-hashing-algorithm-to-speedup-tests">Changing the hashing algorithm to speedup&nbsp;tests</h2>
|
||
<p>By default, Django uses a slow (but secure !) hashing mechanism for checking
|
||
the user credentials. In the tests, we don&#8217;t need this security, but we need
|
||
the&nbsp;speed.</p>
|
||
<p>Changing them to use <span class="caps">MD5</span> turns out to be a way to greatly speed them up! Here
|
||
is how to do it with a pytest fixture&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nd">@pytest</span><span class="o">.</span><span class="n">fixture</span><span class="p">(</span><span class="n">autouse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">password_hasher_setup</span><span class="p">(</span><span class="n">settings</span><span class="p">):</span>
|
||
<span class="c1"># Use a weaker password hasher during tests, for speed</span>
|
||
<span class="n">settings</span><span class="o">.</span><span class="n">PASSWORD_HASHERS</span> <span class="o">=</span> <span class="p">[</span>
|
||
<span class="s2">&quot;django.contrib.auth.hashers.MD5PasswordHasher&quot;</span><span class="p">,</span>
|
||
<span class="p">]</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="speeding-dns-lookups">Speeding <span class="caps">DNS</span>&nbsp;lookups</h2>
|
||
<p>I&#8217;m currently using a MacOSX machine, and for for whatever reason, the local
|
||
lookup was not configured properly on my machine. I don&#8217;t think I did anything
|
||
specific to get this wrong, so it might be your case too. Calls to resolve the
|
||
local domain were tooking&nbsp;5s.</p>
|
||
<p>If the answer to <code>scutil --get LocalHostName</code>, <code>hostname</code> and <code>scutil --get
|
||
HostName</code> differ, then you might be in this case. Here is the fix&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>sudo<span class="w"> </span>scutil<span class="w"> </span>--set<span class="w"> </span>HostName<span class="w"> </span>&lt;YourHostName&gt;
|
||
</code></pre></div></content><category term="code"></category><category term="django"></category><category term="pytest"></category></entry><entry><title>Méditer</title><link href="https://blog.notmyidea.org/mediter.html" rel="alternate"></link><published>2023-04-23T00:00:00+02:00</published><updated>2023-04-23T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-04-23:/mediter.html</id><summary type="html">
|
||
<p>Au printemps et à l&#8217;été dernier, j&#8217;ai du traverser une période de vie assez turbulente, et je me suis mis à des séances quotidiennes de&nbsp;méditation.</p>
|
||
<p>Je n’avais jamais fait ça auparavant, et je dois avouer que je partais un peu sceptique. Traversant une période difficile, j …</p></summary><content type="html">
|
||
<p>Au printemps et à l&#8217;été dernier, j&#8217;ai du traverser une période de vie assez turbulente, et je me suis mis à des séances quotidiennes de&nbsp;méditation.</p>
|
||
<p>Je n’avais jamais fait ça auparavant, et je dois avouer que je partais un peu sceptique. Traversant une période difficile, j’étais vraiment en recherche d’outils pour m’aider à cadrer mes&nbsp;émotions.</p>
|
||
<p>Je n’ai absolument pas été déçu. Je fais 30 mn de méditation par jour, et ce que je pensais être une contrainte est en fait devenu un plaisir, une vraie&nbsp;ressource.</p>
|
||
<p>Après une séance, je me sens plus calme, centré sur moi-même, moins en prise avec mes émotions. La méditation m’offre un endroit où je ne suis pas en train de réfléchir. Je vois les pensées se former, et je contrôle la place que je leur&nbsp;donne.</p>
|
||
<p>Je médite sans être guidé. L’idée pour moi est de me créer un moment de bulle durant laquelle je ne suis pas dérangé, et dont l’objectif est de ne pas donner trop d’importance à mes&nbsp;pensées.</p>
|
||
<p>Bien sur, je ne pense pas que ça fonctionne pour tout le monde et que ce n&#8217;est pas un outil magique, mais il m&#8217;a aidé, alors je&nbsp;partage.</p>
|
||
<p>Voici comment je procède&nbsp;:</p>
|
||
<ul>
|
||
<li><strong>Je me mets une ambiance sonore</strong>, ça m’aide à me concentrer (détails plus&nbsp;loin).</li>
|
||
<li><strong>Je mets tous mes appareils en silencieux</strong> pour ne pas être&nbsp;dérangé.</li>
|
||
<li><strong>Je me mets dans un endroit où je me sens bien</strong> et je me couvre d’une&nbsp;couverture</li>
|
||
<li>C’est parti&nbsp;!</li>
|
||
</ul>
|
||
<h2 id="ce-que-je-fais">Ce que je&nbsp;fais</h2>
|
||
<p>En fin de compte, c’est assez simple : j’essaye de ne pas penser, ou plutôt, d’accepter mes pensées sans leur donner trop d’importance, et sans les&nbsp;minimiser.</p>
|
||
<p>Récemment, je visualise mes pensées comme une sorte de flux, et la méditation est un moyen de m’en extraire temporairement. C’est une image que j’ai en tête quand je médite, je m’imagine au bord de la rivière de mes idées, et je les vois défiler, parfois certaines m’emportent avec elles, j’essaye de le voir et de m’en&nbsp;extraire.</p>
|
||
<p>Parfois, je compte mes inspirations, avec l’envie de ne pas me laisser emporter pas les pensées qui arrivent. Au bout d’un moment, j’ai l’impression de réussir à mettre mon cerveau en&nbsp;pause.</p>
|
||
<p>Ça ressemble pour moi à ce qui se passe quand je fais une sieste : à un moment mon cerveau décroche et m’envoie une sorte de choc de plaisir. La méditation me fait le même effet, mais il est possible d’étendre ce moment de&nbsp;plaisir.</p>
|
||
<p>Parfois, même, je souris&nbsp;!</p>
|
||
<h2 id="ambiance-sonore">Ambiance&nbsp;sonore</h2>
|
||
<p>J’utilise le site <a href="https://mynoise.net/">myNoise</a> qui propose des générateurs qui fonctionnent bien pour moi (on peut venir modifier les niveaux sonores de chaque son). J’aime bien ce site parce qu’il regorge de sons, et qu’il est possible de faire varier d’un jour sur l’autre le cadre sonore de la&nbsp;méditation.</p>
|
||
<p>Je me mets un timer sur le site, avec un « gong » toutes les 10mn, et un <em>fade-out</em> au bout de&nbsp;30mn.</p>
|
||
<p>En voici quelques-uns qui fonctionnent bien pour moi&nbsp;:</p>
|
||
<ul>
|
||
<li><a href="https://mynoise.net/NoiseMachines/primevalEuropeanForestSoundscapeGenerator.php">Les sons de forêt primaire</a> que j’oublie en fait assez&nbsp;rapidement.</li>
|
||
<li><a href="https://mynoise.net/NoiseMachines/singingBowlsDroneGenerator.php">Singing Bowls</a> (en supprimant certains sons qui font trop « cloche » pour&nbsp;moi)</li>
|
||
<li><a href="https://mynoise.net/NoiseMachines/deepVoiceSoundscape.php">Harmoniques et&nbsp;voix</a></li>
|
||
</ul></content><category term="journal"></category></entry><entry><title>Séparation travail et loisirs</title><link href="https://blog.notmyidea.org/separation-travail-et-loisirs.html" rel="alternate"></link><published>2023-02-25T00:00:00+01:00</published><updated>2023-02-25T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-02-25:/separation-travail-et-loisirs.html</id><summary type="html"><blockquote>
|
||
<p>Plus sérieusement, le boulot est le boulot et les loisirs sont aussi la liberté des salariés de faire strictement ce qu’ils veulent de leur temps libre.
|
||
Les trucs « conviviaux » des boites « cool », c’est un moyen très calculé de brouiller la perception travail/loisir et d’induire en fait …</p></blockquote></summary><content type="html"><blockquote>
|
||
<p>Plus sérieusement, le boulot est le boulot et les loisirs sont aussi la liberté des salariés de faire strictement ce qu’ils veulent de leur temps libre.
|
||
Les trucs « conviviaux » des boites « cool », c’est un moyen très calculé de brouiller la perception travail/loisir et d’induire en fait du présentéisme forcené qui n’est rémunéré que de manière très symbolique.
|
||
Et qué s’apelerio&nbsp;exploitation.</p>
|
||
<p>— <a href="https://framapiaf.org/@Monolecte/109924605965899629">Le Monolecte, sur&nbsp;framapiaf</a></p>
|
||
</blockquote>
|
||
<p>Je me questionne sur le double rôle des barrières de protection mises en place au travail, peuvent-elles nous empêcher de créer le monde que l’on veut voir advenir&nbsp;?</p>
|
||
<p>La question de la séparation entre le travail et les loisirs est une question qui en ouvre d’autres pour moi&nbsp;:</p>
|
||
<ul>
|
||
<li>Quelle est la place pour le loisir au travail&nbsp;?</li>
|
||
<li>Le travail est-il nécessairement opposé aux loisirs&nbsp;?</li>
|
||
<li>Quelle place donner aux relations professionnelles hors du milieu pro&nbsp;?</li>
|
||
</ul>
|
||
<h2 id="rationalisation-et-culpabilite">Rationalisation et&nbsp;culpabilité</h2>
|
||
<p>J’entends l’argument de la technique utilisée par les grosses boites pour « paraitre cool » sans rémunérer le travail. C’est un malheureux fait à garder en&nbsp;tête.</p>
|
||
<p>Mais je me demande si derrière cette séparation, il ne se cache pas une idée de sectoriser le travail, de le séparer des aires de loisir, et je ne peux m’empêcher d’y voir le concept de&nbsp;rationalisation.</p>
|
||
<blockquote>
|
||
<p>La <strong>rationalisation</strong> est le phénomène culturel […] constituant l’application de la rationalité à tous les domaines de la vie et depuis tous les échelons de la société. On retrouve ici ce que l’on observait dans le rationalisme : <strong>une propension à privilégier la raison sur toutes les autres fonctions du&nbsp;psychisme.</strong></p>
|
||
<p>En psychologie, psychiatrie et criminologie, c’est l’un des moyens pour le cerveau de « neutraliser la culpabilité » d’un individu coupable d’un acte délictueux ou&nbsp;criminel.</p>
|
||
<p>— <a href="https://fr.wikipedia.org/wiki/Rationalisation?oldformat=true">Rationalisation —&nbsp;Wikipédia</a></p>
|
||
</blockquote>
|
||
<p>Est-ce qu’en séparant le travail du reste de sa vie (pour s’en protéger), on n’effectue pas une gymnastique mentale dont l’objectif serait de ne pas voir les problèmes qui se déroulent au travail ? De « neutraliser la culpabilité » du travail sur nos vies&nbsp;?</p>
|
||
<h2 id="separer-pourquoi">Séparer, pourquoi&nbsp;?</h2>
|
||
<p>À ce stade, il me paraît important de situer cette réflexion sur le plan de l’idéalisme : les conditions de travail n’étant pas les mêmes pour tout le&nbsp;monde.</p>
|
||
<p><strong>Pouvoir mettre le travail à distance</strong> (a.k.a ne pas mettre tous ses œufs dans le même panier) me semble être un des éléments majeurs de cette séparation. Cette aptitude est nécessaire dans un monde ou le travail est vécu comme un moyen d’entretenir une&nbsp;exploitation.</p>
|
||
<p>De l’autre côté du spectre, en situant la réflexion dans un monde où il est possible aux salarié·es de prendre part aux décisions stratégiques, <strong>un des risques de cette rationalisation est de déshumaniser le travail</strong>.</p>
|
||
<p>Jouer au babyfoot (pour reprendre l’exemple du fil mastodon) avec les collègues permettra peut-être d’avoir ensuite des discussions plus détendues, permettra peut-être de créer autre chose que des relations « de travail&nbsp;».</p>
|
||
<p>Se protéger, oui. Garder ses espaces de liberté, oui. Rationaliser ? Plutôt&nbsp;pas.</p>
|
||
<h2 id="questions-ouvertes">Questions ouvertes&nbsp;:</h2>
|
||
<ul>
|
||
<li>Est-ce que des relations créées au travail sont des relations de travail&nbsp;?</li>
|
||
<li>Est-il alors nécessaire de séparer l’un de l’autre&nbsp;?</li>
|
||
<li>Que permet et qu’empêche cette séparation&nbsp;?</li>
|
||
</ul></content><category term="journal"></category><category term="Travail"></category><category term="Facilitation"></category><category term="Savoir-Être"></category></entry><entry><title>Tolérance, empathie et limites</title><link href="https://blog.notmyidea.org/tolerance-empathie-et-limites.html" rel="alternate"></link><published>2023-02-24T00:00:00+01:00</published><updated>2023-02-24T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2023-02-24:/tolerance-empathie-et-limites.html</id><summary type="html"><p>Suite à un message de Yannick sur mastodon, je me suis rendu compte que j&#8217;avais une réaction que je ne comprennais pas. Son message&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Dans la voiture bar d&#8217;un train Paris -&gt; Quimper ;<br>
|
||
Ne pas entendre une blague du « barista » parce que je me suis écarté pour laisser passer …</p></blockquote></summary><content type="html"><p>Suite à un message de Yannick sur mastodon, je me suis rendu compte que j&#8217;avais une réaction que je ne comprennais pas. Son message&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Dans la voiture bar d&#8217;un train Paris -&gt; Quimper ;<br>
|
||
Ne pas entendre une blague du « barista » parce que je me suis écarté pour laisser passer un passager qui retournait en 1ere classe ;<br>
|
||
Faire répéter le barista qui faisait une blague cynique sur la retraire ;<br>
|
||
Réaliser que c&#8217;est <a href="https://fr.wikipedia.org/wiki/Michel-%C3%89douard_Leclerc">Michel Edouard Leclerc</a> qui vient de passer ;<br>
|
||
Se dire que j&#8217;aurais aimé l&#8217;entendre s&#8217;exprimer sur les retraites &#8230;
|
||
— <a href="https://framapiaf.org/@yaf/109916074251295047">Yannick François: &#8220;Dans la voiture bar d&#8217;un train…&#8221; -&nbsp;Framapiaf</a></p>
|
||
</blockquote>
|
||
<p>Auquel j&#8217;ai&nbsp;répondu</p>
|
||
<blockquote>
|
||
<p>Je suis pas sur que tu aurais aimé l&#8217;entendre&nbsp;😧</p>
|
||
</blockquote>
|
||
<p>J&#8217;essaye d&#8217;analyser pourquoi l&#8217;idée me fait réagir et ce que ça vient chercher chez&nbsp;moi. </p>
|
||
<p>D&#8217;un côté j&#8217;ai une envie de justice : je veux confronter ces personnes au monde qu&#8217;il créent et dont ils profitent, d&#8217;un autre côté ça me fait&nbsp;peur. </p>
|
||
<p>Peur de deux choses&nbsp;:</p>
|
||
<ol>
|
||
<li><strong>D&#8217;avoir de l&#8217;empathie pour eux</strong> au moment ou je cherche à les écouter et à les&nbsp;comprendre.</li>
|
||
<li><strong>Peur de ne pas réussir à les écouter</strong> parce que je n&#8217;arrive pas à m&#8217;extraire de mon sentiment d&#8217;impuissance et&nbsp;d&#8217;injustice.</li>
|
||
</ol>
|
||
<p>Je lis bien ma contradiction ici, et je crois que ça cache que <strong>j&#8217;ai peur de les comprendre</strong>.</p>
|
||
<p>Comme si les comprendre rajoutait au problème, comme si en les comprenant ça voulait dire que j&#8217;étais d&#8217;accord avec eux. Pourtant c&#8217;est un des méchanismes que j&#8217;aime le plus : discuter avec des gens avec qui on est en désaccord permet de mieux les comprendre, et donc d&#8217;avoir une meilleure compréhension du&nbsp;monde.</p>
|
||
<p>En fait, j&#8217;ai peur que ma compréhension fasse évluer ma manière de penser : que leurs idées percolent, en les écoutant. Peur que mon monde vacille petit à petit. C&#8217;est une peur que j&#8217;ai aussi rencontrée par le passé, lors de discussions avec des personnes dont les propos me paraissaient dépasser les limites de ce qui est acceptable pour moi, parce qu&#8217;elles font vivre des violences à&nbsp;d&#8217;autres.</p>
|
||
<p>Je me rends compte de ce que ça à d&#8217;étrange : d&#8217;un côté je veux une société libre, libertaire, une société où on écoute les points de vue des un·es et des autres avec bienveillance, où on décide ensemble; et de l&#8217;autre côté je refuse des visions du monde qui ne sont pas les miennes. Mais où placer la limite&nbsp;?</p>
|
||
<p>Il me semble que c&#8217;est le paradoxe de la tolérance. Mais on peut aussi voir la tolérance comme un contrat social, ce qui revient à dire que pour être tolérant envers quelqu&#8217;un·e; il faut que cette personne soit tolérante envers&nbsp;nous.</p>
|
||
<p>Peut-on écouter sans tolérer ? Est-il possible / souhaitable d&#8217;avoir une discussion avec des personnes intolérantes&nbsp;?</p></content><category term="journal"></category><category term="Limites"></category><category term="Savoir-Être"></category></entry><entry><title>Installation de Mosquitto, InfluxDB, Telegraf et Grafana</title><link href="https://blog.notmyidea.org/installation-de-mosquitto-influxdb-telegraf-et-grafana.html" rel="alternate"></link><published>2022-08-29T00:00:00+02:00</published><updated>2022-08-29T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2022-08-29:/installation-de-mosquitto-influxdb-telegraf-et-grafana.html</id><summary type="html"><p>Récemment, on a m&#8217;a demandé un petit coup de main pour aider à l&#8217;installation d&#8217;une pile logicielle qui permet de stocker des données temporelles et en faire des&nbsp;graphiques.</p>
|
||
<p>Voici donc quelques notes prises durant l&#8217;installation du système, concues pour que des personnes qui n&#8217;y …</p></summary><content type="html"><p>Récemment, on a m&#8217;a demandé un petit coup de main pour aider à l&#8217;installation d&#8217;une pile logicielle qui permet de stocker des données temporelles et en faire des&nbsp;graphiques.</p>
|
||
<p>Voici donc quelques notes prises durant l&#8217;installation du système, concues pour que des personnes qui n&#8217;y connaissent pas grand chose puissent s&#8217;y&nbsp;retrouver.</p>
|
||
<p>L&#8217;objectif, c&#8217;est d&#8217;avoir des cartes Arduino qui envoient des données de manière régulière sur un système qui va nous permettre de les stocker et d&#8217;en faire des&nbsp;graphiques.</p>
|
||
<p>Pour ça, nous allons utiliser&nbsp;:</p>
|
||
<ul>
|
||
<li>Un <em>Broker</em> <a href="https://mosquitto.org/">Mosquitto</a> qui va permettre de receptionner les données depuis les différents <em>clients</em>, puis de les dispatcher à qui en a besoin&nbsp;;</li>
|
||
<li>Une base de données <a href="https://www.influxdata.com/products/influxdb-overview/">InfluxDB</a>, qui permet de stocker des données temporelles&nbsp;;</li>
|
||
<li>Un <em>agent</em> <a href="https://www.influxdata.com/time-series-platform/telegraf/">Telegraf</a> qui va prendre les données du broker et les stocker dans la base de données&nbsp;InfluxDB.</li>
|
||
<li><a href="https://grafana.com/">Grafana</a>, une <em>application web</em> qui permet de visualiser les données stockées dans&nbsp;InfluxDB.</li>
|
||
</ul>
|
||
<p>Voici donc un document qui résume les étapes que j&#8217;ai suivies pour mettre en place les différents élements utiles&nbsp;:</p>
|
||
<h2 id="installer-et-se-connecter-au-serveur">Installer et se connecter au&nbsp;serveur</h2>
|
||
<p>Dans notre cas, on est passé par un <span class="caps">VPS</span> chez <span class="caps">OVH</span>, qui tourne sous <a href="https://www.debian.org/">Debian 11</a>, qui a le mérite d&#8217;être une distribution Linux stable, reconnue et (relativement) simple à&nbsp;utiliser.</p>
|
||
<p>Dans un terminal, vous pouvez vous connecter en utilisant la ligne de commande suivante&nbsp;:</p>
|
||
<p><em>Les lignes suivantes sont des lignes d&#8217;invite de commande, on les rencontre assez souvent dans les documentations sur le web. Le signe <code>$</code> signifie le début de la ligne de commande. Le signe <code>#</code> signifie le début des&nbsp;commentaires.</em></p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ssh<span class="w"> </span>utilisateur@adresseip
|
||
</code></pre></div>
|
||
|
||
<p>Une fois connecté, on va mettre à jour les logiciels qui sont présents sur le&nbsp;serveur. </p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>update<span class="w"> </span><span class="c1"># mise à jour des dépôts (la liste des logiciels).</span>
|
||
$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>upgrade<span class="w"> </span><span class="c1"># mise à jour des logiciels.</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="configurer-les-dns">Configurer les <span class="caps">DNS</span></h2>
|
||
<p>Nous allons avoir besoin de deux sous domaines qui redirigent vers le serveur. Bien sur, il faut adapter <code>ndd.tld</code> et le remplacer par votre nom de domaine&nbsp;:</p>
|
||
<ol>
|
||
<li>moquitto.ndd.tld</li>
|
||
<li>graphs.ndd.tld</li>
|
||
</ol>
|
||
<p>Pour faire ça, chez <span class="caps">OVH</span> ça se passe dans la console de « <span class="caps">OVH</span> Cloud », direction « Noms de domaines », et puis il faut rajouter deux enregistrements de type « A » qui pointent vers l&#8217;adresse <span class="caps">IP</span> du&nbsp;serveur.</p>
|
||
<p>En temps normal, l&#8217;adresse <span class="caps">IP</span> vous est fournie par <span class="caps">OVH</span>. Si vous avez un doute, vous pouvez l&#8217;obtenir depuis le serveur avec la commande <code>ip a</code>.</p>
|
||
<h2 id="installer-mosquitto">Installer&nbsp;Mosquitto</h2>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>mosquitto<span class="w"> </span><span class="c1"># installation depuis les dépots officiels</span>
|
||
</code></pre></div>
|
||
|
||
<p>Une fois installé, <a href="https://mosquitto.org/documentation/authentication-methods/">il faut sécuriser l&#8217;installation avec un utilisateur et un mot de passe</a>.</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>mosquitto_passwd<span class="w"> </span>-c<span class="w"> </span>/etc/mosquitto/passwd<span class="w"> </span>&lt;username&gt;
|
||
</code></pre></div>
|
||
|
||
<p>Ensuite dans le fichier de configuration il faut spécifier où est le fichier qui contient les mots de passe. Pour éditer je recommande l&#8217;utilisation de l&#8217;éditeur de texte <code>nano</code>. </p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>nano<span class="w"> </span>/etc/mosquitto/mosquitto.conf
|
||
</code></pre></div>
|
||
|
||
<p>Voici les lignes à rajouter&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>listener 1883
|
||
password_file /etc/mosquitto/passwd
|
||
</code></pre></div>
|
||
|
||
<p>Puis il faut relancer le service mosquitto&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>systemctl<span class="w"> </span>restart<span class="w"> </span>mosquitto
|
||
</code></pre></div>
|
||
|
||
<p>Avant de pouvoir utiliser mosquitto, il faut <a href="https://docs.ovh.com/gb/en/dedicated/firewall-network/">régler le firewall</a> de chez <span class="caps">OVH</span> pour qu&#8217;il accepte de laisser passer les messages pour le broker <span class="caps">MQTT</span>.</p>
|
||
<p>Il faut ajouter une règle dans le Firewall qui laisse passer toutes les connections <span class="caps">TCP</span>, avec l&#8217;option « établie&nbsp;».</p>
|
||
<h3 id="verifions-que-tout-fonctionne-comme-prevu">Vérifions que tout fonctionne comme prévu&nbsp;:</h3>
|
||
<p>Dans une console,&nbsp;écoutons…</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>mosquitto_sub<span class="w"> </span>-h<span class="w"> </span>mosquitto.ndd.tld<span class="w"> </span>-p<span class="w"> </span><span class="m">1883</span><span class="w"> </span>-u<span class="w"> </span>&lt;username&gt;<span class="w"> </span>-P<span class="w"> </span>&lt;password&gt;<span class="w"> </span>-t<span class="w"> </span>topic
|
||
</code></pre></div>
|
||
|
||
<p>Et dans une autre envoyons un message&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>mosquitto_pub<span class="w"> </span>-h<span class="w"> </span>mosquitto.ndd.tld<span class="w"> </span>-p<span class="w"> </span><span class="m">1883</span><span class="w"> </span>-u<span class="w"> </span>&lt;username&gt;<span class="w"> </span>-P<span class="w"> </span>&lt;password&gt;<span class="w"> </span>-t<span class="w"> </span>topic<span class="w"> </span>-m<span class="w"> </span><span class="m">30</span>
|
||
</code></pre></div>
|
||
|
||
<p>Vous deviez voir « 30 » apparaitre dans la première console. Si c&#8217;est bon, tout fonctionne&nbsp;!</p>
|
||
<h2 id="installation-dinfluxdb-et-telegraf">Installation d&#8217;InfluxDB et&nbsp;Telegraf</h2>
|
||
<p>Coup de bol, InfluxDB propose directement des packets pour Debian, sur leur dépot, qu&#8217;il faut donc ajouter en suivant ces quelques lignes&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>-y<span class="w"> </span>gnupg2<span class="w"> </span>curl<span class="w"> </span>wget
|
||
wget<span class="w"> </span>-qO-<span class="w"> </span>https://repos.influxdata.com/influxdb.key<span class="w"> </span><span class="p">|</span><span class="w"> </span>sudo<span class="w"> </span>apt-key<span class="w"> </span>add<span class="w"> </span>-
|
||
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;deb https://repos.influxdata.com/debian </span><span class="k">$(</span>lsb_release<span class="w"> </span>-cs<span class="k">)</span><span class="s2"> stable&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>sudo<span class="w"> </span>tee<span class="w"> </span>/etc/apt/sources.list.d/influxdb.list
|
||
sudo<span class="w"> </span>apt<span class="w"> </span>update
|
||
</code></pre></div>
|
||
|
||
<p>Puis <code>sudo apt install influxdb telegraf</code> pour&nbsp;l&#8217;installer.</p>
|
||
<p>Ensuite, vous pouvez le lancer maintenant et indiquer au système de le lancer tout seul au démarrage&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>systemctl<span class="w"> </span><span class="nb">enable</span><span class="w"> </span>--now<span class="w"> </span>influxdb
|
||
$<span class="w"> </span>sudo<span class="w"> </span>systemctl<span class="w"> </span><span class="nb">enable</span><span class="w"> </span>--now<span class="w"> </span>telegraf
|
||
</code></pre></div>
|
||
|
||
<h3 id="configuration-de-telegraf">Configuration de&nbsp;Telegraf</h3>
|
||
<p>Telegraf permet de faire le lien entre les messages envoyés sur le broker <span class="caps">MQTT</span> et la base de données&nbsp;InfluxDB.</p>
|
||
<p>Ici, il faut rentrer un peu plus dans le vif du sujet, et ça dépends des messages que vous avez à&nbsp;stocker.</p>
|
||
<p>Dans notre cas, nous avons trois types de messages&nbsp;:</p>
|
||
<ul>
|
||
<li>/BatVoltage,&nbsp;int</li>
|
||
<li>/Temperature,&nbsp;int</li>
|
||
<li>/<span class="caps">GPS</span>,&nbsp;string</li>
|
||
</ul>
|
||
<p>Voici un fichier de configuration, qui reste à modifier en fonction des&nbsp;données.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">[global_tags]</span>
|
||
<span class="k">[agent]</span>
|
||
<span class="w"> </span><span class="na">interval</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;10s&quot;</span>
|
||
<span class="w"> </span><span class="na">round_interval</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">true</span>
|
||
<span class="w"> </span><span class="na">metric_batch_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">1000</span>
|
||
<span class="w"> </span><span class="na">metric_buffer_limit</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">10000</span>
|
||
<span class="w"> </span><span class="na">collection_jitter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;0s&quot;</span>
|
||
<span class="w"> </span><span class="na">flush_interval</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;10s&quot;</span>
|
||
<span class="w"> </span><span class="na">flush_jitter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;0s&quot;</span>
|
||
<span class="w"> </span><span class="na">precision</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;0s&quot;</span>
|
||
<span class="w"> </span><span class="na">hostname</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;&quot;</span>
|
||
<span class="w"> </span><span class="na">omit_hostname</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">false</span>
|
||
|
||
<span class="k">[[outputs.influxdb]]</span>
|
||
<span class="w"> </span><span class="na">urls</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">[&quot;http://127.0.0.1:8086&quot;]</span>
|
||
<span class="w"> </span><span class="na">database</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;telegraf&quot;</span>
|
||
|
||
<span class="k">[[inputs.mqtt_consumer]]</span>
|
||
<span class="w"> </span><span class="na">servers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">[&quot;tcp://127.0.0.1:1883&quot;]</span>
|
||
<span class="w"> </span><span class="na">name_override</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;mqtt_consumer_float&quot;</span>
|
||
<span class="w"> </span><span class="na">topics</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">[</span>
|
||
<span class="w"> </span><span class="na">&quot;Topic/BatVoltage&quot;,</span>
|
||
<span class="w"> </span><span class="na">&quot;Topic/Temperature&quot;,</span>
|
||
<span class="w"> </span><span class="na">]</span>
|
||
<span class="w"> </span><span class="na">username</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;&lt;username&gt;&quot;</span>
|
||
<span class="w"> </span><span class="na">password</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;&lt;password&gt;&quot;</span>
|
||
<span class="w"> </span><span class="na">data_format</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;value&quot;</span>
|
||
<span class="w"> </span><span class="na">data_type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&quot;integer&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="installation-de-grafana">Installation de&nbsp;Grafana</h2>
|
||
<div class="highlight"><pre><span></span><code>sudo<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>-y<span class="w"> </span>apt-transport-https
|
||
sudo<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>-y<span class="w"> </span>software-properties-common<span class="w"> </span>wget
|
||
sudo<span class="w"> </span>wget<span class="w"> </span>-q<span class="w"> </span>-O<span class="w"> </span>/usr/share/keyrings/grafana.key<span class="w"> </span>https://packages.grafana.com/gpg.key
|
||
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;deb [signed-by=/usr/share/keyrings/grafana.key] https://packages.grafana.com/oss/deb stable main&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>sudo<span class="w"> </span>tee<span class="w"> </span>-a<span class="w"> </span>/etc/apt/sources.list.d/grafana.list
|
||
sudo<span class="w"> </span>apt<span class="w"> </span>update
|
||
sudo<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>grafana
|
||
sudo<span class="w"> </span>/bin/systemctl<span class="w"> </span>daemon-reload
|
||
sudo<span class="w"> </span>/bin/systemctl<span class="w"> </span><span class="nb">enable</span><span class="w"> </span>grafana-server
|
||
sudo<span class="w"> </span>/bin/systemctl<span class="w"> </span>start<span class="w"> </span>grafana-server
|
||
</code></pre></div>
|
||
|
||
<h3 id="nginx">Nginx</h3>
|
||
<div class="highlight"><pre><span></span><code>sudo apt install nginx certbot python3-certbot-nginx
|
||
</code></pre></div>
|
||
|
||
<p>Puis il faut créer un fichier de configuration dans <code>/etc/nginx/sites-enabled/graphs.ndd.tld</code> avec le contenu suivant&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">map</span><span class="w"> </span><span class="nv">$http_upgrade</span><span class="w"> </span><span class="nv">$connection_upgrade</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kn">default</span><span class="w"> </span><span class="s">upgrade</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">&#39;&#39;</span><span class="w"> </span><span class="s">close</span><span class="p">;</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="k">upstream</span><span class="w"> </span><span class="s">grafana</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kn">server</span><span class="w"> </span><span class="n">localhost</span><span class="p">:</span><span class="mi">3000</span><span class="p">;</span>
|
||
<span class="p">}</span>
|
||
|
||
<span class="k">server</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">server_name</span><span class="w"> </span><span class="s">graphs.ndd.tld</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">root</span><span class="w"> </span><span class="s">/usr/share/nginx/html</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">index</span><span class="w"> </span><span class="s">index.html</span><span class="w"> </span><span class="s">index.htm</span><span class="p">;</span>
|
||
|
||
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Host</span><span class="w"> </span><span class="nv">$http_host</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://grafana</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="c1"># Proxy Grafana Live WebSocket connections.</span>
|
||
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/api/live/</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kn">proxy_http_version</span><span class="w"> </span><span class="mi">1</span><span class="s">.1</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Upgrade</span><span class="w"> </span><span class="nv">$http_upgrade</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Connection</span><span class="w"> </span><span class="nv">$connection_upgrade</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">proxy_set_header</span><span class="w"> </span><span class="s">Host</span><span class="w"> </span><span class="nv">$http_host</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="kn">proxy_pass</span><span class="w"> </span><span class="s">http://grafana</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>Une fois ces fichiers de configuration en place, il faut penser à la mise en place du <span class="caps">SSL</span> qui permet d&#8217;avoir une connexion sécurisée&nbsp;(https).</p>
|
||
<p>Il suffit de lancer cette ligne de commande et de suivre les questions posées&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>sudo certbot --nginx
|
||
</code></pre></div>
|
||
|
||
<p>Voilà ! A ce moment là, tout doit être fonctionnel, il ne reste plus qu&#8217;à configurer le Grafana pour grapher les données enregistrées dans&nbsp;InfluxDB.</p></content><category term="code"></category><category term="Administration Système"></category></entry><entry><title>Réveil difficile</title><link href="https://blog.notmyidea.org/reveil-difficile.html" rel="alternate"></link><published>2022-05-30T00:00:00+02:00</published><updated>2022-05-30T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2022-05-30:/reveil-difficile.html</id><summary type="html"><p>La discussion avait été transcendante. Difficile, même : mes repères s&#8217;estompaient, semblaient flous et d&#8217;un seul coup, se refermer sur moi-même. Je réalisais que ma place était ailleurs. Pas ailleurs physiquement, mais ailleurs <em>mentalement</em>. Je réalisais que les préceptes qui « dirigeaient » ma vie, de manière tellement certaine, tellement évidente …</p></summary><content type="html"><p>La discussion avait été transcendante. Difficile, même : mes repères s&#8217;estompaient, semblaient flous et d&#8217;un seul coup, se refermer sur moi-même. Je réalisais que ma place était ailleurs. Pas ailleurs physiquement, mais ailleurs <em>mentalement</em>. Je réalisais que les préceptes qui « dirigeaient » ma vie, de manière tellement certaine, tellement évidente, venaient de&nbsp;bouger.</p>
|
||
<p>Comme si je sortais d&#8217;un ensorcellement, que mon comportement — ma perception, même — avaient étés durant des années différents, et que, enfin, je me réveillais. Avec un arrière-goût amer dans le fond du&nbsp;palais.</p>
|
||
<p>L&#8217;incantation ne commençait pas : ses effets finissaient par disparaître. Comme sorti du brouillard, une certitude : bien que je n&#8217;étais pas le seul à réaliser le sort qui m&#8217;avait été réservé, beaucoup d&#8217;autres n&#8217;en avaient pas du tout conscience. Voire même : ceux qui n&#8217;en avaient pas conscience semblaient évoluer dans ce qui me semblait maintenant une béatitude <em>malaisante</em>.</p>
|
||
<p>Certain⋅e⋅s s&#8217;injectaient même volontairement des <em>doses</em> de cette <em>potion</em> pour que le brouillard ne se dissipe pas. Et je comprends pourquoi : les effets sont puissants, ils rendent les frontières lisses, colorent les interstices, remplacent les malaises par des joies&nbsp;candides.</p>
|
||
<p>Malgré ça, je suis content d&#8217;entrevoir maintenant le monde comme il est réellement. Je suis content de refuser cette vérité qui n&#8217;en est pas une, cette science occulte&nbsp;destructrice.</p>
|
||
<p>J&#8217;entrouvre les yeux par delà le brouillard, et il ne fait pas spécialement beau. J&#8217;aurais voulu,&nbsp;pourtant.</p></content><category term="journal"></category><category term="Poésie"></category></entry><entry><title>L’Ère de la critique</title><link href="https://blog.notmyidea.org/lere-de-la-critique.html" rel="alternate"></link><published>2022-05-07T00:00:00+02:00</published><updated>2022-05-07T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2022-05-07:/lere-de-la-critique.html</id><summary type="html"><p>Au détour d&#8217;<a href="https://tutut.delire.party/@almet/108257053355480866">une discussion sur mastodon</a> je viens de retrouver ce bout de texte écrit mais jamais&nbsp;publié.</p>
|
||
<p>J&#8217;y parle de ce que formuler des critiques me fait, de la hiérarchisation qui en découle, et de ce qu&#8217;elle me fait à moi mais aussi aux&nbsp;producteurs⋅ices …</p></summary><content type="html"><p>Au détour d&#8217;<a href="https://tutut.delire.party/@almet/108257053355480866">une discussion sur mastodon</a> je viens de retrouver ce bout de texte écrit mais jamais&nbsp;publié.</p>
|
||
<p>J&#8217;y parle de ce que formuler des critiques me fait, de la hiérarchisation qui en découle, et de ce qu&#8217;elle me fait à moi mais aussi aux&nbsp;producteurs⋅ices.</p>
|
||
<p>——</p>
|
||
<p>Voici un chemin que je semble parcourir depuis quelques années, de manières répétées mais sans m&#8217;en rendre&nbsp;compte.</p>
|
||
<p>Je commence par découvrir : tout est génial, un nouveau monde qui s&#8217;explore, de nouvelles personnes, de nouveaux termes, de nouvelles&nbsp;envies.</p>
|
||
<p>Et puis je cherche mieux, plus fort, plus surprenant. Il faut désormais analyser, comparer, trouver des critères pour hiérarchiser, pour tendre vers mieux — (mais pourquoi ? peut-être pour chercher à montrer que <em>je suis (le) meilleur</em>&nbsp;?)</p>
|
||
<p>Plusieurs choses semblent découler de ce mécanisme&nbsp;:</p>
|
||
<ol>
|
||
<li>
|
||
<p>Mon niveau d&#8217;attente peut s&#8217;élever, à tel point qu&#8217;il faudrait bientôt la perfection pour me rendre&nbsp;heureux.</p>
|
||
</li>
|
||
<li>
|
||
<p>Les personnes qui créent ce que j&#8217;écoute, ce que je lis, ce que j&#8217;utilise, ce que je mange, ce que je pense; ces personnes sont comparées à d&#8217;autres. D&#8217;autres qui font mieux, plus grand, plus&nbsp;beau.</p>
|
||
</li>
|
||
<li>
|
||
<p>Je me renferme sur ce que j&#8217;apprécie pour ses qualités intrinsèques, sans considération pour le contexte. J&#8217;en viens alors à manquer de profiter de ce qui se fait <em>ici</em>, en y préférant ce qui se fait <em>là bas</em>.</p>
|
||
</li>
|
||
</ol>
|
||
<h2 id="ne-pas-se-mettre-la-pression">Ne pas (se) mettre la&nbsp;pression</h2>
|
||
<p>Une chose que j&#8217;ai apprise en devenant brasseur, c&#8217;est qu&#8217;il est facile de <em>se comparer</em> à d&#8217;autres, de se mettre la pression. Je crois cette pression néfaste me fait rentrer dans un jeu de compétition — et non pas de saine émulation — où je compare toujours ce que je fais a ce que d&#8217;autres font. Je n&#8217;apprécie plus les choses pour ce qu&#8217;elles sont, mais pour ce qu&#8217;elle ne sont pas, pour ce qui leur&nbsp;manque.</p>
|
||
<p>Je produis également cette pression — sur d&#8217;autres — quand je juge et&nbsp;classe.</p>
|
||
<p>Après quelques années à fabriquer de la bière, je sais maintenant «ce que je vaux » et donc les critiques extérieures m&#8217;impactent moins que par le passé, mais avant d&#8217;arriver à cette connaissance de moi même, ces comparaisons ne me facilitaient pas la&nbsp;vie.</p>
|
||
<h2 id="intellectualisation-vs-emotions">Intellectualisation vs&nbsp;Émotions</h2>
|
||
<p>En cherchant à intellectualiser mes ressentis, en cherchant à analyser ce que je <em>vis</em>, est-ce que je n&#8217;oublie pas d&#8217;aller puiser dans mes émotions ? En analysant <em>de trop</em>, est-ce que je ne me prive pas de mes ressentis&nbsp;?</p>
|
||
<h2 id="vers-une-ethique-de-la-critique">Vers une éthique de la critique&nbsp;?</h2>
|
||
<p>Il semble alors que se poser quelques questions permette d&#8217;y voir plus clair&nbsp;:</p>
|
||
<ol>
|
||
<li><strong>Questionner mon niveau d&#8217;attente</strong> : Quel est mon niveau d&#8217;attente ? Où s&#8217;arrête le « bien » et où commence l&#8217;exceptionnel&nbsp;?</li>
|
||
<li><strong>Sortir de la compétition</strong> : Suis-je en (ou en train de rentrer en) compétition avec ce que je juge ? Pourquoi&nbsp;?</li>
|
||
<li><strong>Questionner l&#8217;impact de mes critiques</strong> sur les autres et sur&nbsp;moi-même;</li>
|
||
<li><strong>Rechercher le plaisir</strong> : Est-ce que je trouve du plaisir dans le fait de faire une critique ? et si oui est-ce sain ? Est-ce une critique constructive&nbsp;?</li>
|
||
</ol></content><category term="journal"></category><category term="Savoir-Être"></category></entry><entry><title>Fatigue relationnelle</title><link href="https://blog.notmyidea.org/fatigue-relationnelle.html" rel="alternate"></link><published>2022-05-06T00:00:00+02:00</published><updated>2022-05-06T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2022-05-06:/fatigue-relationnelle.html</id><summary type="html"><p>Depuis peu, je me retrouve confronté à mon manque d&#8217;envie d&#8217;être avec d&#8217;autres personnes. Comme si mon quota d’interactions sociales était plus rapidement atteint qu&#8217;il y a quelques&nbsp;années.</p>
|
||
<p>Je ne sais pas exactement d&#8217;où cela vient : si c&#8217;est un des nombreux effets …</p></summary><content type="html"><p>Depuis peu, je me retrouve confronté à mon manque d&#8217;envie d&#8217;être avec d&#8217;autres personnes. Comme si mon quota d’interactions sociales était plus rapidement atteint qu&#8217;il y a quelques&nbsp;années.</p>
|
||
<p>Je ne sais pas exactement d&#8217;où cela vient : si c&#8217;est un des nombreux effets psychologiques que le <span class="caps">COVID</span> à eu sur moi, si j&#8217;accorde trop de place aux collectifs dans ma vie (travail, habitation, ami⋅es), ou si simplement mes envies ne sont plus les mêmes qu&#8217;il y a quelques années, mais le résultat est bel et bien&nbsp;là.</p>
|
||
<p>Malgré tout j&#8217;ai envie d&#8217;être disponible pour les personnes qui comptent pour moi, et je réfléchis donc à différentes solutions : déménager et habiter en solo, faire moins d&#8217;activités extérieures ou bien m&#8217;isoler plus souvent dans les espaces&nbsp;collectifs.</p>
|
||
<p>Le fait de retourner potentiellement habiter en solo vient questionner mon rapport au collectif omniprésent dans ma vie, et qui jouit d&#8217;un statut particulier pour moi. Le collectif semble être quasiment un <em>objectif en soi</em>, et donc quelque-part partir de ces espaces collectifs serait une sorte&nbsp;d&#8217;échec.</p>
|
||
<p>Entrouvrir cette possibilité me plaît parce-que ça me pousse à accepter mes limites et à mettre en balance ma qualité de relation aux autres avec mes valeurs collectivistes. Du collectif, oui, mais peut-être avec un mix différent&nbsp;?</p>
|
||
<p>Ça fait également écho à ma <a href="conflit.html">gestion du conflit</a>. Je me rends compte que j&#8217;ai besoin d&#8217;évoluer dans des collectifs qui partagent cette culture de la gestion du conflit (plutôt que de son&nbsp;évitement).</p></content><category term="journal"></category><category term="Coopération"></category><category term="Savoir-Être"></category><category term="Fatigue"></category><category term="Conflit"></category></entry><entry><title>Conflit</title><link href="https://blog.notmyidea.org/conflit.html" rel="alternate"></link><published>2021-11-11T00:00:00+01:00</published><updated>2021-11-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-11-11:/conflit.html</id><summary type="html"><p>J&#8217;ai pensé durant de nombreuses années que je savais gérer le conflit, alors que c&#8217;était en fait&nbsp;impensé.</p>
|
||
<p>Ne pas être en conflit signifie parfois s&#8217;adapter aux autres, parfois ne pas (assez) s&#8217;écouter, et ne pas se faire&nbsp;entendre. </p>
|
||
<p><strong>Alors que je pensais gérer le conflit …</strong></p></summary><content type="html"><p>J&#8217;ai pensé durant de nombreuses années que je savais gérer le conflit, alors que c&#8217;était en fait&nbsp;impensé.</p>
|
||
<p>Ne pas être en conflit signifie parfois s&#8217;adapter aux autres, parfois ne pas (assez) s&#8217;écouter, et ne pas se faire&nbsp;entendre. </p>
|
||
<p><strong>Alors que je pensais gérer le conflit, je l&#8217;évitais</strong>.</p>
|
||
<p>J&#8217;apprends donc à définir mes attentes de manière claire, à nommer mes désaccords de manière à en faire des sujets de discussion, plutôt que de les lisser pour « tomber d&#8217;accord », quitte à m&#8217;oublier au&nbsp;passage.</p>
|
||
<p>Il me semble maintenant indispensable de me questionner afin de connaître ma position <em>avant</em> de considérer que mon avis n&#8217;est pas important, et parfois <strong>oser tenir tête</strong> quand j&#8217;estime que l&#8217;enjeu le&nbsp;justifie.</p>
|
||
<p>Toute la question devient donc la question de la stratégie à adopter pour que les sujets importants à mes yeux soient perçus comme tels pour mes&nbsp;interlocuteurs⋅rices.</p>
|
||
<p>Je suis content de faire cette découverte&nbsp;:-)</p></content><category term="journal"></category><category term="Savoir-Être"></category><category term="Coopération"></category><category term="Conflit"></category></entry><entry><title>Coopération et travail</title><link href="https://blog.notmyidea.org/cooperation-et-travail.html" rel="alternate"></link><published>2021-11-01T00:00:00+01:00</published><updated>2021-11-01T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-11-01:/cooperation-et-travail.html</id><summary type="html"><p>Je parle souvent de coopération, que j&#8217;imagine comme « un fonctionnement collectif, dans lequel chacun⋅e y trouve son compte&nbsp;».</p>
|
||
<p>Or je me rends aujourd&#8217;hui compte que cette définition mets de côté les interactions entre les concerné⋅es, et (surtout) leurs&nbsp;modalités.</p>
|
||
<p>Autrement dit : la coopération ne devrait pas …</p></summary><content type="html"><p>Je parle souvent de coopération, que j&#8217;imagine comme « un fonctionnement collectif, dans lequel chacun⋅e y trouve son compte&nbsp;».</p>
|
||
<p>Or je me rends aujourd&#8217;hui compte que cette définition mets de côté les interactions entre les concerné⋅es, et (surtout) leurs&nbsp;modalités.</p>
|
||
<p>Autrement dit : la coopération ne devrait pas être un moyen que chacun⋅e y trouve son compte, mais <strong>une capacité à faire ensemble</strong>. C&#8217;est une pratique, plutôt qu&#8217;un&nbsp;résultat.</p>
|
||
<p><em>Je découvre qu&#8217;il s&#8217;agit d&#8217;un mode de fonctionnement qui n&#8217;est pas évident pour tout le monde au quotidien</em>.</p>
|
||
<p>Notre mode de fonctionnement actuel au travail est de nous séparer les tâches, décision prise pour diminuer la charge de travail de chacun : il nous faut être&nbsp;efficaces.</p>
|
||
<p>Mais cette séparation ne nous permet pas d&#8217;apprendre à faire ensemble. C&#8217;est une séparation des tâches, plutôt qu&#8217;une réelle&nbsp;coopération.</p>
|
||
<p>Plutôt que de faire les choses en collaboration, on choisit donc de faire les choses chacun⋅e dans son coin, en ayant nos zones d&#8217;expertises, nos décisions qui nous incombent et notre&nbsp;responsabilité.</p>
|
||
<p><strong>Je me questionne sur la culture que produit ce mode de fonctionnement</strong> : j&#8217;ai l&#8217;impression que chez moi cela produit de l&#8217;isolement. J&#8217;aimerais alors plutôt chercher à cultiver le « faire ensemble », pour favoriser les moments d&#8217;échange et de&nbsp;transmission.</p>
|
||
<p>Peut-être est-ce justement parce que les savoirs techniques m&#8217;ennuient rapidement que <strong>j&#8217;ai besoin de ces moments de transmission ? Ceux-cis ne seraient alors pour moi pas un moyen mais un objectif</strong>.</p>
|
||
<p>Je ne me sens pas toujours plainement satisfait dans mon travail actuel, et je cherche à comprendre ce qui cause cet état : il semble que je m&#8217;ennuie vite quand je me retrouve seul face à des problématiques qui pourraient bénéficier d&#8217;une&nbsp;discussion.</p>
|
||
<h2 id="un-autre-travail-de-deconstruction">Un autre travail de&nbsp;déconstruction</h2>
|
||
<p><em>Pour ce paragraphe j&#8217;ai longuement hésité entre le « je » et le « on », ayant l&#8217;impression d&#8217;être parfois le sujet et parfois l&#8217;observateur des comportements décrits. J&#8217;ai finalement opté pour le « je » en guise d&#8217;exercice de remise en question&nbsp;personnelle.</em></p>
|
||
<p>Malheureusement, je — on — me mets parfois en compétition, ce qui empêche justement cette coopération / collaboration d&#8217;avoir&nbsp;lieu.</p>
|
||
<p>Plutôt que d&#8217;apprendre par l&#8217;observation — « Ah tiens, ça c&#8217;est une faiblesse chez moi, je devrais travailler dessus », « Ah tiens, c&#8217;est intéressant la manière dont iel s&#8217;empare de telle problématique » — je &#8220;bloque&#8221; parfois l&#8217;apprentissage en me construisant une image de moi-même meilleure qu&#8217;elle n&#8217;est en réalité, peut-être pour éviter d&#8217;affronter mes propres&nbsp;faiblesses.</p>
|
||
<p>Pourtant, les considérer comme des faiblesses semble une étape indispensable pour pouvoir ensuite les&nbsp;soigner.</p>
|
||
<p>Mais impossible d&#8217;activer cette manière de concevoir le rapport à l&#8217;autre quand je suis en compétition : je passe alors mon temps à me rassurer sur ma manière d&#8217;être. Je veux absolument me trouver meilleur que je ne suis en&nbsp;réalité.</p>
|
||
<p>Pour sortir de ce mode de fonctionnement, il me faut chercher à apprendre des autres, souligner mes faiblesses pour les travailler, plutôt que de refuser de les pointer du&nbsp;doigt.</p></content><category term="journal"></category><category term="Coopération"></category><category term="Travail"></category></entry><entry><title>Rentrée</title><link href="https://blog.notmyidea.org/rentree.html" rel="alternate"></link><published>2021-09-13T00:00:00+02:00</published><updated>2021-09-13T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-09-13:/rentree.html</id><summary type="html">
|
||
<p>Trois semaines de vacances m&#8217;ont fait le plus grand bien. Je suis toujours autant étonné par ma capacité à repousser mes limites quand je suis la tête dans le guidon, ce qui était le cas fin&nbsp;Juillet.</p>
|
||
<p>J&#8217;ai mis quasiment une semaine à retrouver un rythme « naturel » et …</p></summary><content type="html">
|
||
<p>Trois semaines de vacances m&#8217;ont fait le plus grand bien. Je suis toujours autant étonné par ma capacité à repousser mes limites quand je suis la tête dans le guidon, ce qui était le cas fin&nbsp;Juillet.</p>
|
||
<p>J&#8217;ai mis quasiment une semaine à retrouver un rythme « naturel » et à ne plus me sentir fatigué, <strong>alors que je pensais prendre soin de moi jusqu&#8217;ici</strong>. Ma capacité d&#8217;auto-analyse semble donc me faire défaut, il faut que je travaille&nbsp;dessus.</p>
|
||
<p>J&#8217;ai profité de ces trois semaines de repos pour prendre du recul et pour prendre des décisions de fond. Et ça fait du&nbsp;bien.</p>
|
||
<h2 id="numerique">Numérique</h2>
|
||
<p>Cette vieille rengaine de mon rapport au numérique continue à suivre son bout de chemin : je me considère comme un drogué qui n&#8217;arrive pas vraiment à décrocher. Ces quelques semaines sans ordinateur ont encore nourri cette envie de m&#8217;éloigner de mon mode de consommation des&nbsp;écrans.</p>
|
||
<p>Je continue ma chasse aux temps d&#8217;écran non souhaités, pour éviter que des heures y disparaissent sans que ce soit quelque chose que j&#8217;ai prévu et souhaité, et je cherche à les remplacer par d&#8217;autres&nbsp;moments.</p>
|
||
<p>L&#8217;avantage étant que j&#8217;ai bien préparé le terrain ces dernières années et que les projets numériques pour lesquels je suis indispensable sont beaucoup moins&nbsp;nombreux.</p>
|
||
<p>Il me reste un chemin non négligeable à parcourir en ce qui concerne la musique electronique : beaucoup de ma pratique se passe sur écran, et les options pour m&#8217;en passer sont&nbsp;couteuses.</p>
|
||
<p>Je me suis remis à faire beaucoup de guitare durant ces trois semaines, et j&#8217;y ai trouvé un plaisir différent. La piste « synthés physiques » commence à se dégager, bien qu&#8217;encore trop couteuse pour que je m&#8217;y&nbsp;abandonne.</p>
|
||
<h2 id="cooperative">Coopérative</h2>
|
||
<p>On est en train de passer le pas vers un modèle de type <span class="caps">SCOP</span> pour la brasserie, et c&#8217;est loin d&#8217;être une mince&nbsp;affaire.</p>
|
||
<p>Contrairement à ce que j&#8217;imaginais au début de ma réflexion, on a fait l&#8217;erreur de monter d&#8217;abord une <span class="caps">SARL</span> et on en paye le prix (au sens propre)&nbsp;aujourd&#8217;hui.</p>
|
||
<p>Aussi, ça a été un vrai travail de vouloir lâcher les rennes du bébé : ça veut dire faire un saut vers l&#8217;inconnu, lâcher du contrôle et faire confiance aux autres et au&nbsp;futur.</p>
|
||
<p>Un peu moins de pouvoir mais plus de puissance&nbsp;:-)</p>
|
||
<p>J&#8217;ai beaucoup apprécié la manière dont mon associé actuel pense la chose. « Puisqu&#8217;on cherche à créer un lieu de travail démocratique, c&#8217;est la seule solution. » (ou en tout cas c&#8217;est comme ça que j&#8217;ai&nbsp;compris).</p>
|
||
<p>J&#8217;ai l&#8217;espoir que certains rapports de pouvoir incarnés par les rôles administratifs de co-gérance vont pouvoir être transcendés par ce nouveau mode&nbsp;d&#8217;organisation.</p>
|
||
<h2 id="limites-et-travail">Limites et&nbsp;travail</h2>
|
||
<p>J&#8217;ai choisi de remplacer mes semaines de 4 journées (de parfois 10h !) par 5 journées moins longues, et je ne regrette rien&nbsp;jusqu&#8217;ici.</p>
|
||
<p>J&#8217;essaye de tenir des limites horaires qui me font rentrer tôt du travail pour gagner une première partie de soirée dont j&#8217;avais oublié l’existence&nbsp;(16h-19h).</p>
|
||
<p>J&#8217;essaye également de <strong>dire non plus souvent</strong> aux sollicitations dans le cadre du travail. Je suis souvent étonné par le poids que les attentes extérieures font peser sur ma vie de&nbsp;producteur.</p>
|
||
<p>Le fameux « Être chef⋅fe d&#8217;entreprise, c&#8217;est travailler beaucoup, c&#8217;est se sacrifier pour son travail », et ça passe par bien des interstices : être présent⋅e à l&#8217;<span class="caps">AMAP</span> le soir, travailler les week-ends sur des salons, décaler ses horaires pour être arrangeant,&nbsp;etc.</p>
|
||
<p>Des temps parfois agréables et nécessaires, mais qui n&#8217;en sont pas moins du travail. A moi de les considérer comme tels, quitte à les refuser si&nbsp;besoin.</p>
|
||
<h2 id="attentes-relationnelles">Attentes&nbsp;relationnelles</h2>
|
||
<p>Une de mes révélations de ces vacances a été de me rendre compte des attentes que je fais parfois peser sur mes relations personnelles, et du stress qui en&nbsp;résulte.</p>
|
||
<p>Considérer les relations pour ce qu&#8217;elles sont — plutôt que ce qu&#8217;elles ne sont pas — me permet de faire baisser considérablement la pression que je crée à leur endroit, et de les laisser s&#8217;exprimer de manière plus&nbsp;naturelle.</p>
|
||
<p>Ça me permet également d&#8217;être plus naturel, et de faire baisser la pression que je peux parfois me mettre tout&nbsp;seul.</p></content><category term="journal"></category></entry><entry><title>Faire de la musique sous Linux</title><link href="https://blog.notmyidea.org/faire-de-la-musique-sous-linux.html" rel="alternate"></link><published>2021-08-04T00:00:00+02:00</published><updated>2021-08-04T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-08-04:/faire-de-la-musique-sous-linux.html</id><summary type="html">
|
||
<p><em>Update du 07/08 : ajout des infos sur le noyau temps&nbsp;réel</em></p>
|
||
<p>Faire de la musique electronique à été pour moi l&#8217;occasion de réinstaller Windows pour pouvoir utiliser <a href="https://www.ableton.com/en/live/">Ableton Live</a>, un des logiciels les plus utilisés dans le domaine. J&#8217;étais content de passer du temps à faire de …</p></summary><content type="html">
|
||
<p><em>Update du 07/08 : ajout des infos sur le noyau temps&nbsp;réel</em></p>
|
||
<p>Faire de la musique electronique à été pour moi l&#8217;occasion de réinstaller Windows pour pouvoir utiliser <a href="https://www.ableton.com/en/live/">Ableton Live</a>, un des logiciels les plus utilisés dans le domaine. J&#8217;étais content de passer du temps à faire de la musique plutôt que du temps à faire tomber les choses en marche, même si mon éthique n&#8217;était pas tout à fait&nbsp;d&#8217;accord.</p>
|
||
<p>C&#8217;est un choix que je ne regrette pas : je me suis vraiment amusé, j&#8217;ai <a href="https://soundcloud.com/the-lost-triangle/">fait quelques morceaux</a> et j&#8217;ai pu goûter au plaisir du truc. Un des avantages d&#8217;apprendre en utilisant des outils <em>mainstrem</em>, c&#8217;est qu&#8217;il y a beaucoup de ressources disponibles (tutoriels vidéo, ami⋅es), ce qui m&#8217;a beaucoup facilité la tache dans la découverte du&nbsp;domaine.</p>
|
||
<p>Et puis, <a href="https://yohanboniface.me/">Yohan</a> m&#8217;a parlé de <a href="https://www.bitwig.com/">Bitwig</a>, un logiciel de type « Digital Audio Workstation » (<span class="caps">DAW</span>) qui tourne nativement sous Linux, et après une petite scéance de test j&#8217;ai eu envie de creuser un peu le sujet de l&#8217;audio sous&nbsp;Linux.</p>
|
||
<p>L&#8217;occasion donc d&#8217;installer une station musicale sous Linux (j&#8217;utilise <a href="https://archlinux.org/">Arch Linux</a>). Ça marche plutôt bien, ce n&#8217;est pas trop long à mettre en place (une fois qu&#8217;on sait quoi faire), même si ça reste moins simple que sous Windows. Je suis très content du résultat&nbsp;!</p>
|
||
<h2 id="configuration">Configuration</h2>
|
||
<p>Installer Arch n&#8217;est pas très compliqué, mais passe par de la ligne de commande, c&#8217;était l&#8217;occasion de réviser un peu mes classiques, mais je peux comprendre que ce soit intimidant. Si vous voulez avoir un installeur graphique, il me semble que <a href="https://manjaro.org/">Manjaro</a> (un dérivé d&#8217;Arch) en propose&nbsp;un.</p>
|
||
<h3 id="configuration-du-noyau-linux">Configuration du noyau&nbsp;Linux</h3>
|
||
<p>Ça me paraissait compliqué, et pourtant c&#8217;était très simple ! J&#8217;ai utilisé le noyau « linux-zen » avec quelques options spécifiques « threadirqs » et le mode « performance » pour les&nbsp;processeurs.</p>
|
||
<p>J&#8217;ai du installer un paquet logiciel pour avoir des privilèges « temps réel » indispensable pour l&#8217;audio : sans ça le plugin <span class="caps">VST</span> « Kontakt » plantait directement au&nbsp;lancement.</p>
|
||
<div class="highlight"><pre><span></span><code>sudo<span class="w"> </span>pacman<span class="w"> </span>-S<span class="w"> </span>realtime-privileges
|
||
sudo<span class="w"> </span>gpasswd<span class="w"> </span>-a<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$USER</span><span class="s2">&quot;</span><span class="w"> </span>realtime
|
||
</code></pre></div>
|
||
|
||
<div class="highlight"><pre><span></span><code>yay<span class="w"> </span>linux-zen
|
||
yay<span class="w"> </span>rtirq
|
||
</code></pre></div>
|
||
|
||
<p>Édition de <code>/etc/default/grub</code> pour utiliser threadirqs et passer le scheduling du processeur en « performance&nbsp;».</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nv">GRUB_CMDLINE_LINUX_DEFAULT</span><span class="o">=</span><span class="s2">&quot;loglevel=3 quiet threadirqs cpufreq.default_governor=performance&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<div class="highlight"><pre><span></span><code><span class="c1"># Regénérer la configuration de grub</span>
|
||
grub-mkconfig<span class="w"> </span>-o<span class="w"> </span>/boot/grub/grub.cfg
|
||
|
||
<span class="c1"># S&#39;assurer que « fsync » soit bien utilisé par wine.</span>
|
||
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;export WINEFSYNC=1&quot;</span><span class="w"> </span>&gt;&gt;<span class="w"> </span>~/.profile
|
||
|
||
<span class="c1"># Ajout au groupe audio</span>
|
||
sudo<span class="w"> </span>gpasswd<span class="w"> </span>-a<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$USER</span><span class="s2">&quot;</span><span class="w"> </span>realtime
|
||
</code></pre></div>
|
||
|
||
<p>Le <span class="caps">DAW</span> <a href="https://www.bitwig.com/">Bitwig</a> que j&#8217;utilise n&#8217;est pas open source, mais tourne nativement sous Linux. Son installation sous Arch est vraiment on ne peut plus simple : <code>yay bitwig-studio</code>.</p>
|
||
<h2 id="vsts-instruments-virtuels">VSTs (Instruments&nbsp;virtuels)</h2>
|
||
<p>J&#8217;ai acheté quelques <span class="caps">VST</span> qui tournent nativement sous Linux mais également d&#8217;autres qui n&#8217;ont pas de version Linux native. C&#8217;est par exemple le cas de&nbsp;Kontakt.</p>
|
||
<p>Dans ce cas, il faut passer par le pont logiciel <a href="https://github.com/robbert-vdh/yabridge">yabridge</a> ainsi qu&#8217;une version récente de wine : <a href="https://github.com/Frogging-Family/wine-tkg-git/releases/">wine-tkg</a>.</p>
|
||
<p>Pour installer yabridge, <code>yay yabridge-bin</code>.</p>
|
||
<p>Installation de wine-tkg&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>wget<span class="w"> </span>https://github.com/Frogging-Family/wine-tkg-git/releases/download/6.11.r4.g0dd44a25/wine-tkg-staging-fsync-git-6.11.r4.g0dd44a25-326-x86_64.pkg.tar.zst
|
||
sudo<span class="w"> </span>pacman<span class="w"> </span>-U<span class="w"> </span>wine-tkg-staging-fsync-git-6.11.r4.g0dd44a25-326-x86_64.pkg.tar.zst
|
||
</code></pre></div>
|
||
|
||
<h3 id="installation-dun-vst-kontakt">Installation d&#8217;un <span class="caps">VST</span>&nbsp;(Kontakt)</h3>
|
||
<p>Ensuite, installez le <span class="caps">VST</span> dans wine&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>wine<span class="w"> </span>Kontakt<span class="se">\ </span><span class="m">6</span>.3.0<span class="se">\ </span>Setup<span class="se">\ </span>PC.exe
|
||
<span class="nb">cd</span><span class="w"> </span>patch
|
||
wine<span class="w"> </span>Kontakt<span class="se">\_</span>patch<span class="se">\_</span>installer<span class="se">\_</span><span class="m">6</span><span class="se">\_</span>3_0.exe
|
||
</code></pre></div>
|
||
|
||
<p>Spécifiez l&#8217;emplacement pour les <span class="caps">VST64</span> : <code>C:\Program Files\Steinberg\VstPlugins</code> (emplacement souvent utilisé pour les <span class="caps">VST2</span>), je ne sais pas pour quelle raison mais utiliser un emplacement classique peut résoudre des&nbsp;bugs.</p>
|
||
<p>Une fois installé, vous pouvez ajouter le fichier qui contient vos VSTs dans yabridge&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>yabridgectl<span class="w"> </span>add<span class="w"> </span><span class="s2">&quot;/home/alexis/.wine/drive_c/Program Files/Steinberg/VstPlugins&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>Puis faire <code>yabridgectl sync</code> qui va générer les .<code>so</code> (format Linux) à partir des <code>.dll</code> (format&nbsp;Windows).</p>
|
||
<p>Il ne reste plus qu&#8217;à ajouter le dossier qui contient les <span class="caps">VST</span> dans Bitwig et c&#8217;est bon&nbsp;!</p>
|
||
<p>J&#8217;utilise sans soucis ces instruments Kontakt&nbsp;:</p>
|
||
<ul>
|
||
<li>Una Corda&nbsp;(Piano)</li>
|
||
<li>Studio Drummer&nbsp;(Batterie)</li>
|
||
</ul>
|
||
<p><img alt="bitwig-studio-studio-drummer.png" src="/images/musique-linux.png"></p>
|
||
<h2 id="carte-son">Carte&nbsp;son</h2>
|
||
<p>J&#8217;utilise une carte son Scarlett 18i8 gen3, qui fonctionne nativement pour sortir de l&#8217;audio et pour en capturer. Par contre certains controles ne sont pas exposés, et le logiciel de contrôle / configuration ne tourne pas sous&nbsp;wine.</p>
|
||
<p>Mais… (coup de bol ?) quelqu&#8217;un s&#8217;est motivé <a href="https://github.com/geoffreybennett/scarlett-gen2">pour écrire le code noyau</a> qui permet de faire ça nativement. Ça vient d&#8217;être mergé dans le noyau Linux, et devrait être disponible avec le kernel 5.14, qui devrait bientôt voir le jour (c&#8217;est la <span class="caps">RC3</span> au moment ou j&#8217;écris ces&nbsp;lignes).</p>
|
||
<h2 id="controleurs">Controleurs</h2>
|
||
<p>J&#8217;utilise un <a href="https://novationmusic.com/en/keys/launchkey-mini">Novation Launchkey mini mk3</a> avec les mappings proposés par <a href="http://mossgrabers.de/Software/Bitwig/Bitwig.html">DrivenByMoss</a> qui permettent de controller nativement Bitwig, c&#8217;est assez bluffant, ça marche tout seul&nbsp;!</p>
|
||
<p>Installation&nbsp;:</p>
|
||
<ol>
|
||
<li>Télécharger l&#8217;archive qui contient le code depuis le site&nbsp;web</li>
|
||
<li>Extraire le fichier .bwextension dans <code>~/Bitwig Studio/Extensions</code></li>
|
||
</ol>
|
||
<p>Il semble aussi que <a href="http://www.mossgrabers.de/Software/Bitwig/Bitwig.html">Push 2 pour Bitwig sous Linux</a> soit une option interessante (mais bien plus couteuse)&nbsp;!</p>
|
||
<h2 id="vst-natif-linux"><span class="caps">VST</span> natif&nbsp;Linux</h2>
|
||
<p>Il existe un tas de <span class="caps">VST</span> open source qui font très bien le taf. J&#8217;aime beaucoup toute la collection de <span class="caps">VST</span> sans interface graphique (et open source !) qui est proposée par airwindows, (installables avec <code>yay aur/airwindows-git</code>)</p>
|
||
<p>J&#8217;utilise quelques <span class="caps">VST</span> payants également. Ceux que j&#8217;utilise actuellement, et qui sont compatibles Linux&nbsp;:</p>
|
||
<ul>
|
||
<li>Les instruments de chez <a href="https://tal-software.com/"><span class="caps">TAL</span></a>. J&#8217;utilise <a href="https://tal-software.com/products/tal-mod"><span class="caps">TAL</span>-Mod</a> pour faire des bonnes grosses&nbsp;basses</li>
|
||
<li>Ceux de chez <a href="https://u-he.com/products/">U-he</a>. J&#8217;utilise <a href="https://u-he.com/products/bazille/">Bazille</a>, un Synthé modulaire polyphonique avec des oscillateurs numériques et de la <span class="caps">FM</span>)</li>
|
||
</ul>
|
||
<p>Une grosse liste est présente sur <a href="http://linux-sound.org/linux-vst-plugins.html">Linux Sound</a> si vous voulez creuser&nbsp;:-)</p>
|
||
<h2 id="configuration-pour-du-temps-reel">Configuration pour du temps&nbsp;réel</h2>
|
||
<p>Edititon du 7/08 : j&#8217;ai pu jouer un peu depuis, et je me suis rendu compte que j&#8217;avais quelques glitches audio quand j&#8217;utilisais wine. J&#8217;ai donc fait quelques changements&nbsp;supplémentaires.</p>
|
||
<p>Ressources&nbsp;:</p>
|
||
<ul>
|
||
<li><a href="https://github.com/robbert-vdh/yabridge#performance-tuning">Le wiki de yabridge sur le tuning&nbsp;perfomance</a></li>
|
||
<li><a href="https://github.com/raboof/realtimeconfigquickscan">Un outil pour faire un scan des problèmes de perf&nbsp;connus</a></li>
|
||
</ul></content><category term="journal"></category></entry><entry><title>Vaccination et risques</title><link href="https://blog.notmyidea.org/vaccination-et-risques.html" rel="alternate"></link><published>2021-05-08T00:00:00+02:00</published><updated>2021-05-08T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-05-08:/vaccination-et-risques.html</id><summary type="html"><p>Je m&#8217;intéresse un peu tardivement a la question des différents vaccins, pour pouvoir mieux comprendre comment ceux cis fonctionnent et quels sont les risques&nbsp;liés.</p>
|
||
<p>Cette réflexion n&#8217;est en aucun cas pro- ou anti- vaccin, mais cherche simplement à essayer de comprendre et faire un petit tour d …</p></summary><content type="html"><p>Je m&#8217;intéresse un peu tardivement a la question des différents vaccins, pour pouvoir mieux comprendre comment ceux cis fonctionnent et quels sont les risques&nbsp;liés.</p>
|
||
<p>Cette réflexion n&#8217;est en aucun cas pro- ou anti- vaccin, mais cherche simplement à essayer de comprendre et faire un petit tour d&#8217;horizon des critiques formulées à leur égard par les scientifiques. Considérez cette page comme des notes que j&#8217;ai fait pour moi même et que je&nbsp;publie.</p>
|
||
<h2 id="les-differents-types-de-virus">Les différents types de&nbsp;virus</h2>
|
||
<p>J&#8217;ai d&#8217;abord essayé de comprendre quels étaient les différents types de&nbsp;virus.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Type de virus</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Virus nus</td>
|
||
<td>Une coque de protéine (capside), qui renferme le matériel génétique du virus.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Virus enveloppés</td>
|
||
<td>En plus de la capside, une enveloppe avec une protéine de surface (« Spike » dans le cas de <span class="caps">SARS</span>-<span class="caps">COV2</span>). Ici « spike » permet aux virus de pénétrer dans les cellules pour y libérer son matériel génétique.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Il existe différents types de matériel génétique : l&#8217;<span class="caps">ADN</span> et l&#8217;<span class="caps">ARN</span>. </p>
|
||
<p>L&#8217;<span class="caps">ADN</span> contient des gènes, qui détiennent les « plans » pour la fabrication des protéines (qui permettent d&#8217;effectuer les processus biologiques de nos cellules) ; L&#8217;<span class="caps">ADN</span> doit d&#8217;abord être transcris en ARNm (transcription) puis ensuite il y a une conversion de l&#8217;<span class="caps">ARN</span> vers la protéine, appelée « traduction&nbsp;». </p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Type de matériel génétique</th>
|
||
<th>Fonctionnement du virus</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><span class="caps">ADN</span></td>
|
||
<td>Injecte directement son matériel génétique dans la cellule qu&#8217;il infecte. La cellule va ensuite transcrire l&#8217;<span class="caps">ADN</span> en <span class="caps">ARN</span>, puis fabriquer les protéines virales, qui vont s&#8217;assembler pour former de nouveaux virus et coloniser les autres cellules /individus en cascade.</td>
|
||
</tr>
|
||
<tr>
|
||
<td><span class="caps">ARN</span></td>
|
||
<td>C&#8217;est le cas du <span class="caps">SARS</span>-<span class="caps">COV2</span>. Le virus injecte directement l&#8217;<span class="caps">ARN</span>, comme au dessus.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="les-vaccins">Les&nbsp;vaccins</h2>
|
||
<p>Les vaccins stimulent notre système immunitaire pour faire face au virus / bactéries le jour ou c&#8217;est utile. L&#8217;idée étant de neutraliser les agents infectieux avant qu&#8217;ils ne fassent des&nbsp;dégâts.</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Type de vaccin</th>
|
||
<th>Fonctionnement</th>
|
||
<th>Inconvénients</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Injection du virus inactivé</td>
|
||
<td>On injecte le virus inactivé (formaldheide ou traitement physique type irradiation aux <span class="caps">UV</span>). Le virus est toujours immunisant.</td>
|
||
<td>- Souvent assez peu immunogènes. Il faut donc ajouter des adjuvants (sels d&#8217;aluminium, formaldhéide…). <br />- Il faut aussi multiplier les doses</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Vaccin vivant</td>
|
||
<td>Souvent, une souche thermosensible du virus, qui fait qu&#8217;il n&#8217;est plus capable de se multiplier à la température de notre corps. Plus immunogènes que les virus inactivés</td>
|
||
<td>Plus grande prise de risque, notamment pour les personnes fragiles, immunodéprimées</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Vaccins à protéines recombinantes</td>
|
||
<td>Plutôt que d&#8217;injecter le virus entier, on injecte une protéine du virus (par ex la protéine de surface), pour stimuler notre système immunitaire.<br /><br />On isole le gène qui permet de fabriquer la protéine en question, et on fait en sorte que le gène s&#8217;exprime, pour le multiplier en labo (bioreacteurs, fermenteurs) puis on lui adjoint des adjuvants et on l&#8217;injecte. (protéine vaccinante)</td>
|
||
<td>?</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<h2 id="les-vaccins-genetiques-de-type-arnm">Les vaccins « génétiques » de type&nbsp;ARNm</h2>
|
||
<p>Ils consistent à injecter dans les cellules de la personne à vacciner, une partie du matériel génétique du virus, qui détient les « plans » pour fabriquer la protéine de&nbsp;surface.</p>
|
||
<p>On fait fabriquer ces protéines directement par les cellules des personnes à vacciner. Ça peut être de l&#8217;<span class="caps">ARN</span> ou de l&#8217;<span class="caps">ADN</span>. L&#8217;<span class="caps">ADN</span> ou l&#8217;<span class="caps">ARN</span> sont encapsulés dans un&nbsp;vecteur.</p>
|
||
<p>Dans le cadre de l&#8217;<span class="caps">ARN</span>, il s&#8217;agit d&#8217;une nano-particule de graisse, qui vient se fixer directement sur les nos cellules (la membrane&nbsp;plasmique).</p>
|
||
<h2 id="les-vaccins-genetiques-de-type-adn">Les vaccins « génétiques » de type <span class="caps">ADN</span></h2>
|
||
<p>Il est aussi possible d&#8217;avoir des vaccins génétiques à <span class="caps">ADN</span>. On utilise dans ce cas un autre virus (un adénovirus, rendu inactif), comme vecteur pour pouvoir injecter l&#8217;<span class="caps">ADN</span>. Dans ce cas on vient éliminer une partie de l&#8217;<span class="caps">ADN</span> de l&#8217;adénovirus et on le remplace par de l&#8217;<span class="caps">ADN</span> qui code les protéines qu&#8217;on cherche à reproduire (celles de surface « Spike » dans le cas du <span class="caps">SARS</span>-<span class="caps">COV2</span>).</p>
|
||
<p>On appelle ça un virus&nbsp;recombinant.</p>
|
||
<p>l&#8217;<span class="caps">ARN</span> du virus <span class="caps">SARS</span>-<span class="caps">COV2</span> à été converti en <span class="caps">ADN</span> par des enzymes virales (trouvées dans les rétrovirus) « transcriptases inverses » puis ensuite ajoutées dans&nbsp;l&#8217;adénovirus.</p>
|
||
<h3 id="risques">Risques</h3>
|
||
<p>Selon Christian Vélot et le <span class="caps">CRIIGEN</span> (association anti-<span class="caps">OGM</span>), les risques sont les suivants&nbsp;:</p>
|
||
<ul>
|
||
<li>
|
||
<p><strong>Risques d&#8217;intégration de l&#8217;<span class="caps">ADN</span></strong> vaccinant dans nos propres chromosomes. Il y a eu des tests dans le cas de thérapies géniques (ou on essaye de remplacer un gène muté par un gène « réparateur / normal »), le problème étant qu&#8217;on ne maitrise pas l&#8217;endroit ou il peut s&#8217;insérer. Dans certains cas, l&#8217;<span class="caps">ADN</span> réparateur est allé s&#8217;insérer dans des oncogènes, menant à des&nbsp;leucémies.</p>
|
||
</li>
|
||
<li>
|
||
<p><strong>Risque de réactions immunitaires inopportunes</strong>&nbsp;(immuno-toxicité)</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="risques-communs-aux-vaccins-arnm-et-adn">Risques communs aux vaccins ARNm et <span class="caps">ADN</span></h2>
|
||
<blockquote>
|
||
<p>Les virus ont une grande capacité à échanger des fragments de leur matériel génétique respectif dès lors que les génomes viraux concernés sont de même nature (soit <span class="caps">ADN</span>, soit <span class="caps">ARN</span>) et qu’ils partagent des séquences (des gènes) qui se ressemblent. Le processus bien connu qui régit ces échanges s’appelle la recombinaison (et lorsque cette recombinaison a lieu entre séquences d’<span class="caps">ADN</span> ou d’<span class="caps">ARN</span> qui se ressemblent, on parle de recombinaison homologue). Ce phénomène de recombinaison n’est pas réservé à l’<span class="caps">ADN</span> ou l’<span class="caps">ARN</span> viral mais les séquences virales sont connues pour faire l’objet de nombreuses recombinaisons (on dit qu’elles sont très « recombinogènes »). Il résulte de <strong>ces recombinaisons, entre matériels génétiques viraux</strong>, des virus dits « recombinants » dont le ou les gène(s) qui a (ont) été le site de ces échanges sont dits « mosaïques », c’est-à-dire <strong>constitués en partie de séquences provenant du virus 1 et de séquences provenant du virus 2</strong>.</p>
|
||
<p>ce phénomène ne peut se produire que si du matériel génétique provenant d’au moins deux virus se retrouve dans les mêmes cellules, ce qui est fort heureusement extrêmement rare dans la nature puisque cela implique que des mêmes cellules soient co-infectées par au moins deux&nbsp;virus. </p>
|
||
<p>— <a href="https://criigen.org/wp-content/uploads/2020/12/2020-09_Note-dExpertise-Vaccins-GM_C.Ve%CC%81lot-06.pdf">Christian Vélot</a>, <span class="caps">CRIIGEN</span>, Septembre&nbsp;2020</p>
|
||
</blockquote>
|
||
<p>Selon Christian Vélot, il y a un risque de recombinaison virale : les virus de même nature (<span class="caps">ARN</span> entre eux, <span class="caps">ADN</span> entre eux) aiment échanger du matériel génétique entre eux. Et c&#8217;est d&#8217;autant plus fréquent entre virus de la même&nbsp;famille.</p>
|
||
<p>Les virus recombinants peuvent être plus ou moins dangereux, et il est difficile de le savoir à l&#8217;avance. <span class="caps">H1N1</span> étant par exemple un virus&nbsp;recombinant.</p>
|
||
<p>Pour que ça arrive, il faut que la même cellule soit infectée par deux virus au même moment. <strong>Ce qui est extrêmement peu probable</strong>. Dès lors qu&#8217;on introduit du matériel génétique viral dans une cellule, il suffit qu&#8217;un autre virus de même nature infecte la même cellule pour qu&#8217;il y ait un échange entre le matériel génétique vaccinant et&nbsp;contaminant.</p>
|
||
<p>C&#8217;est très très peu probable, mais dans le cas ou ça arriverait, cela pourrait mener à émergence d&#8217;un nouveau&nbsp;virus. </p>
|
||
<p>Suite à la lecture d&#8217;<a href="https://www.mdpi.com/2076-393X/9/5/453">un papier sur les risques liés aux vaccins de type <span class="caps">ARN</span></a>, il semble qu&#8217;il faille deux choses&nbsp;:</p>
|
||
<blockquote>
|
||
<p>As with other viral vectors, a potential hazard associated with adenoviral vector based vaccines is the reversion to replication competency following homologous recom-bination&nbsp;events.</p>
|
||
</blockquote>
|
||
<ol>
|
||
<li>Que le virus inactivé se réactive&nbsp;;</li>
|
||
<li>Qu&#8217;il y ait une recombinaison liée à la présence d&#8217;un autre virus dans la même&nbsp;cellule.</li>
|
||
</ol>
|
||
<blockquote>
|
||
<p>Nevertheless, the absence of replication competent adenoviruses (<span class="caps">RCA</span>) should be demonstrated by the manufacturers for each batch release of the adenoviral vectored vaccine candidate as part of the routine quality&nbsp;control </p>
|
||
</blockquote>
|
||
<p>Il est tout de même demandé aux fabriquant de vaccins de prouver que les vaccins/virus ne peuvent pas se&nbsp;reproduire.</p>
|
||
<blockquote>
|
||
<p>Emergence of <span class="caps">RCA</span> might also occur after administration of the vaccine by homologous recombination events between the adenoviral vector based vaccine sequences and the parental wild-type virus or other related human adenovirus infecting the same host&nbsp;cell.</p>
|
||
</blockquote>
|
||
<p>C&#8217;est pour cette raison que les adenovirus qui sont utilisés sont des virus qu&#8217;on ne trouve pas chez&nbsp;l&#8217;homme.</p>
|
||
<blockquote>
|
||
<p>In the scenario that <span class="caps">RCA</span> and replication competent chimeric adenoviral vectors are shed by vaccinees, the general population and the environment might be exposed. Potential adverse effects on human health and the environment of replication competent chimeric viruses are unclear although a decreased replication capacity of adenovirus chime-ras from different species has been&nbsp;reported.</p>
|
||
</blockquote>
|
||
<p>C&#8217;est donc un risque réel qui est pris, mais qui a été&nbsp;étudié. </p>
|
||
<h2 id="les-types-de-vaccins-contre-sars-cov2">Les types de vaccins contre <span class="caps">SARS</span>-<span class="caps">COV2</span></h2>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nom</th>
|
||
<th>Type</th>
|
||
<th>Notes</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Sinofarm (chinois)</td>
|
||
<td>Vaccin inactivé</td>
|
||
<td>Releasé avant les essais cliniques de phase 3.</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Novavax</td>
|
||
<td>Protéines recombinantes</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Medicago (Canada)</td>
|
||
<td>Protéine recombinante</td>
|
||
<td>Protéines de la capside, donc pas la protéine de surface</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Sanofi-pasteur</td>
|
||
<td>Protéine recombinante</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Pfizer-BioNTech</td>
|
||
<td>ARNm</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Moderna</td>
|
||
<td>ARNm</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Astrazeneca</td>
|
||
<td><span class="caps">ADN</span> et adénovirus recombinant</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Spoutnik</td>
|
||
<td><span class="caps">ADN</span> et adénovirus recombinant</td>
|
||
<td></td>
|
||
</tr>
|
||
</tbody>
|
||
</table></content><category term="journal"></category><category term="Santé"></category><category term="Vaccination"></category><category term="Covid"></category></entry><entry><title>Facebook, compétition, éthique et marketing.</title><link href="https://blog.notmyidea.org/facebook-competition-ethique-et-marketing.html" rel="alternate"></link><published>2021-01-26T00:00:00+01:00</published><updated>2021-01-26T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-01-26:/facebook-competition-ethique-et-marketing.html</id><summary type="html">
|
||
<p>En créant la <a href="https://www.vieuxsinge.com">brasserie du Vieux Singe</a>, le fait de créer une <em>page facebook</em> s&#8217;est posé comme une évidence. Il s&#8217;agit de l&#8217;outil <em>de facto</em> pour communiquer avec son « audience&nbsp;».</p>
|
||
<p>J&#8217;ai donc créé une page pour notre nouvelle entreprise, et au fur et à mesure je …</p></summary><content type="html">
|
||
<p>En créant la <a href="https://www.vieuxsinge.com">brasserie du Vieux Singe</a>, le fait de créer une <em>page facebook</em> s&#8217;est posé comme une évidence. Il s&#8217;agit de l&#8217;outil <em>de facto</em> pour communiquer avec son « audience&nbsp;».</p>
|
||
<p>J&#8217;ai donc créé une page pour notre nouvelle entreprise, et au fur et à mesure je me suis mis à utiliser ce compte pour « suivre » les pages des autres brasseries, question de se tenir&nbsp;informé.</p>
|
||
<p>Et puis je me suis rendu compte qu&#8217;être surexposé aux nouvelles des autres brasseries à suscité chez moi un sentiment de faiblesse. Une sorte de « syndrome de la compétition ». Au début, je suis rentré un peu dans le jeu : toujours plus, toujours&nbsp;mieux.</p>
|
||
<p>Il faut tenir les gens informés, avoir toujours des nouvelles fraîches. Sans me l&#8217;avouer, je crois que je cherchais quelque part à impressionner, à être <em>cool</em>. Comme si la nouveauté était plus importante que le fait de « faire les choses bien », dans les règles de l&#8217;art, en portant mes&nbsp;valeurs.</p>
|
||
<p>Je me retrouvais à créer un avatar, une marque que les gens doivent aimer. On en vient presque à oublier qu&#8217;on est faillibles, parfois fragiles. Surtout, il ne faut pas montrer ce côté là. Une sorte de vision viriliste de&nbsp;l&#8217;entreprenariat.</p>
|
||
<p>Je crois maintenant que reconnaître cette fragilité est important, c&#8217;est ce qui me permet de voir les choses en face, de refuser une dissociation cognitive entre d&#8217;un côté ce que je veux être et de l&#8217;autre ce que je suis&nbsp;vraiment.</p>
|
||
<p>Je ne peux m&#8217;empêcher de faire un parallèle avec Mozilla, chez qui cette dissociation — image lisse d&#8217;un côté, réalité de fonctionnement pyramidal de l&#8217;autre — m&#8217;a posé problème durant mon passage la&nbsp;bas.</p>
|
||
<p>Les stratégies de communication demandent de maintenir tout le monde excité en permanence, amenant à une baisse de la nuance dans mon discours. Mais en suivant cette logique, que se passera-t-il ensuite ? Il devient de plus en plus compliqué d&#8217;être&nbsp;original…</p>
|
||
<h2 id="marketing-ethique">Marketing&nbsp;éthique</h2>
|
||
<p>Nous avons décidé de garder notre page Facebook, parce que — qu&#8217;on le souhaite ou non — beaucoup de personnes utilisent ce média pour se tenir au courant, mais nous avons également décidé de de changer la manière dont nous l&#8217;utilisons&nbsp;:</p>
|
||
<ol>
|
||
<li>
|
||
<p>Facebook n&#8217;est plus l&#8217;endroit où nous postons nos messages, il s&#8217;agit simplement d&#8217;un relai d&#8217;info. On envoie également des mails, et on publie les informations sur notre site&nbsp;web.</p>
|
||
</li>
|
||
<li>
|
||
<p>Nous postons rarement, mais nous essayons de poster du contenu de qualité. Bien-sûr des informations sur nos sorties de bières, mais également des retours d&#8217;expérience, des projets, etc. L&#8217;idée étant de sortir de la course aux&nbsp;nouveautés.</p>
|
||
</li>
|
||
<li>
|
||
<p>Également, après un petit temps <em>dans la compétition</em>, j&#8217;ai choisi d&#8217;en sortir en me désinscrivant de toutes les pages suivies sur Facebook. Si Facebook doit être un relai, très bien, mais j&#8217;ai d&#8217;autres sources d&#8217;informations — moins toxiques — de mon côté. Radical, mais efficace&nbsp;!</p>
|
||
</li>
|
||
</ol>
|
||
<p>Cela fait maintenant un an et demi que je suis ces quelques règles, et je pense que les effets délétères du média social se tassent&nbsp;;-)</p></content><category term="journal"></category></entry><entry><title>Routine</title><link href="https://blog.notmyidea.org/routine.html" rel="alternate"></link><published>2021-01-25T00:00:00+01:00</published><updated>2021-01-25T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-01-25:/routine.html</id><summary type="html">
|
||
<blockquote>
|
||
<p>Si vous pensez que l&#8217;aventure est dangereuse, je vous propose d&#8217;essayer la routine&#8230;. Elle est mortelle&nbsp;!</p>
|
||
<p>— Paulo&nbsp;Coelho</p>
|
||
</blockquote>
|
||
<p>J&#8217;ai toujours attaché une connotation négative à la&nbsp;routine.</p>
|
||
<p>La routine, c&#8217;est l&#8217;ennui ; c&#8217;est la peur de reproduire toujours la même chose ; de me retrouver bloqué …</p></summary><content type="html">
|
||
<blockquote>
|
||
<p>Si vous pensez que l&#8217;aventure est dangereuse, je vous propose d&#8217;essayer la routine&#8230;. Elle est mortelle&nbsp;!</p>
|
||
<p>— Paulo&nbsp;Coelho</p>
|
||
</blockquote>
|
||
<p>J&#8217;ai toujours attaché une connotation négative à la&nbsp;routine.</p>
|
||
<p>La routine, c&#8217;est l&#8217;ennui ; c&#8217;est la peur de reproduire toujours la même chose ; de me retrouver bloqué dans un fonctionnement que je reproduis parce qu&#8217;il a fonctionné un jour. Dans mon imaginaire, la routine c&#8217;est se satisfaire du&nbsp;status-quo.</p>
|
||
<p>Pourtant, à y regarder de plus près il semble que je manquais une partie de&nbsp;l&#8217;histoire.</p>
|
||
<blockquote>
|
||
<ol>
|
||
<li>Capacité, faculté acquise plutôt par une longue habitude, par une longue pratique, que par le secours de l’étude et des&nbsp;règles.</li>
|
||
<li>Usage depuis longtemps consacré de faire une chose toujours de la même&nbsp;manière.</li>
|
||
</ol>
|
||
<p>— Définition de « routine » sur le <a href="https://fr.wiktionary.org/wiki/routine">Wikitionnaire</a></p>
|
||
</blockquote>
|
||
<p>Il me semble qu&#8217;il n&#8217;y a pas nécessairement de connotation négative derrière cette notion de routine. Je me demande si les routines ne seraient pas même un moyen pour « apprendre sans en avoir l&#8217;air »&nbsp;?</p>
|
||
<p>Il me semble également que les routines permettent d&#8217;obtenir une quiétude. Se questionner (une fois), décider, puis faire de manière routinière, sans se poser à nouveau la même question sans&nbsp;cesse.</p>
|
||
<p>Ça vient me questionner à beaucoup d&#8217;endroits, de ma gestion quotidienne de mon temps à mon rapport à l&#8217;apprentissage. Ça me&nbsp;plait.</p></content><category term="journal"></category></entry><entry><title>Reconnexion ?</title><link href="https://blog.notmyidea.org/reconnexion.html" rel="alternate"></link><published>2021-01-15T00:00:00+01:00</published><updated>2021-01-15T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2021-01-15:/reconnexion.html</id><summary type="html">
|
||
<p>Cela fait un an que <a href="https://blog.notmyidea.org/break-technologique.html">j&#8217;ai décidé de me déconnecter</a> pour laisser plus de place à d&#8217;autres&nbsp;projets.</p>
|
||
<blockquote>
|
||
<p>Me détacher de la maintenance de ihatemoney ;
|
||
Supprimer la plupart des applications sur mes téléphones (pro et perso)
|
||
Éteindre mon serveur personnel ;
|
||
Ne plus ramener mon téléphone pro à la …</p></blockquote></summary><content type="html">
|
||
<p>Cela fait un an que <a href="https://blog.notmyidea.org/break-technologique.html">j&#8217;ai décidé de me déconnecter</a> pour laisser plus de place à d&#8217;autres&nbsp;projets.</p>
|
||
<blockquote>
|
||
<p>Me détacher de la maintenance de ihatemoney ;
|
||
Supprimer la plupart des applications sur mes téléphones (pro et perso)
|
||
Éteindre mon serveur personnel ;
|
||
Ne plus ramener mon téléphone pro à la maison ;
|
||
Avoir un ordinateur fixe au travail, et l&#8217;y laisser&nbsp;;</p>
|
||
</blockquote>
|
||
<p>Cette partie de la liste est entièrement validée, et cela m&#8217;apporte une quiétude. La frontière entre le travail et le perso est maintenant mieux définie. A la fois pour moi, pour mes collègues et pour mes ami·es. J&#8217;en retire beaucoup de&nbsp;repos.</p>
|
||
<blockquote>
|
||
<p>Limiter mon utilisation de l&#8217;ordinateur perso à 1h par jour, sauf exceptions&nbsp;;</p>
|
||
</blockquote>
|
||
<p>Je passe dans l&#8217;ensemble beaucoup moins de temps sur l&#8217;ordinateur, même si le téléphone portable à pris une place plus importante, ce que je&nbsp;regrette.</p>
|
||
<p>J&#8217;ai transitionné d&#8217;une utilisation de l&#8217;ordinateur pour écrire des logiciels à une utilisation pour fabriquer de la musique. J&#8217;y découvre un plaisir, en partie parce que l&#8217;outil est puissant, en partie parce que je découvre un moyen de réaliser des envies qui trottent dans ma tête depuis quelques temps.
|
||
Mais… je me retrouve encore derrière un&nbsp;écran.</p>
|
||
<p>Je creuse petit à petit l&#8217;utilisation d&#8217;outils qui permettent de se passer de <em>Digital Audio Workstation</em> (<span class="caps">DAW</span>) — et donc d&#8217;ordinateur — mais j&#8217;avoue ne pas trop y croire pour&nbsp;l&#8217;instant.</p>
|
||
<p>Peut-être que ce qui me gène n&#8217;est pas tant l&#8217;écran en tant que tel, mais la posture dans laquelle celui-ci me plonge&nbsp;?</p>
|
||
<p>Plutôt que de chercher à passer <strong>très peu</strong> de temps derrière un écran, je peux essayer de maximiser le temps ou j&#8217;y fais quelque chose qui m&#8217;intéresse, et pour lequel je suis dans un usage créatif&nbsp;?</p></content><category term="journal"></category></entry><entry><title>Forum ouvert, animation et posture</title><link href="https://blog.notmyidea.org/forum-ouvert-animation-et-posture.html" rel="alternate"></link><published>2020-03-06T00:00:00+01:00</published><updated>2020-03-06T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-03-06:/forum-ouvert-animation-et-posture.html</id><summary type="html"><p>Début Février j&#8217;ai participé à un Forum Ouvert. Il s&#8217;agit de la troisième fois, et cette fois ci j&#8217;étais particulièrement attentif aux procédés mis en place pour sa tenue, puisque je faisais partie de l&#8217;équipe&nbsp;d&#8217;organisation.</p>
|
||
<h2 id="un-forum-ouvert">Un forum ouvert&nbsp;?</h2>
|
||
<p>Les forums ouverts sont des outils …</p></summary><content type="html"><p>Début Février j&#8217;ai participé à un Forum Ouvert. Il s&#8217;agit de la troisième fois, et cette fois ci j&#8217;étais particulièrement attentif aux procédés mis en place pour sa tenue, puisque je faisais partie de l&#8217;équipe&nbsp;d&#8217;organisation.</p>
|
||
<h2 id="un-forum-ouvert">Un forum ouvert&nbsp;?</h2>
|
||
<p>Les forums ouverts sont des outils qui permettent de se retrouver avec un groupe de personnes et d&#8217;avoir des échanges. L&#8217;idée est de créer un cadre assez léger qui permette aux personnes d&#8217;échanger de manière assez&nbsp;horizontale.</p>
|
||
<p>Les 4 principes&nbsp;:</p>
|
||
<ul>
|
||
<li>les personnes présentes sont les bonnes personnes&nbsp;;</li>
|
||
<li>quoi qu&#8217;il arrive, c&#8217;est la seule chose qui pouvait arriver&nbsp;;</li>
|
||
<li>ça commence quand ça commence&nbsp;;</li>
|
||
<li>quand c’est fini, c’est&nbsp;fini.</li>
|
||
</ul>
|
||
<p>La loi de la mobilité ou loi des deux pieds : si à un moment vous vous rendez compte que vous n&#8217;être ni en train d’apprendre, ni de contribuer, aller voir autre chose&nbsp;!</p>
|
||
<p>Retours&nbsp;:</p>
|
||
<ul>
|
||
<li>
|
||
<p>J&#8217;étais hyper surpris de voir à quel point l&#8217;outil est fonctionnel en tant que tel : les discussions auxquelles j&#8217;ai pu participer étaient souvent assez « poussées » alors même que les personnes ne se connaissaient pas d&#8217;avant le&nbsp;forum.</p>
|
||
</li>
|
||
<li>
|
||
<p>Durant le forum ouvert, il y avait la possibilité de prendre des notes, et de les partager avec tout le monde dans un espace prévu pour ça. Je n&#8217;y croyais pas trop, mais ça à vraiment fonctionné ! On avait préparé des pads en ligne (un espace de prise de notes partagées) avant l&#8217;évènement ce qui à permis de faciliter la prise de notes&nbsp;;</p>
|
||
</li>
|
||
<li>
|
||
<p>Avoir un endroit pour afficher les notes prises durant les discussions est utile, et créé un sentiment de satisfaction collectif&nbsp;;</p>
|
||
</li>
|
||
<li>
|
||
<p>Répartition de la parole : à un moment, on propose aux participant⋅e⋅s de venir proposer des sujets, et on s&#8217;est rendu compte que c&#8217;était (comme bien trop souvent) en grande partie des hommes cis (assignés hommes à la naissance) qui prenaient la parole à ce moment là. Pour éviter que ce ne soit le cas, laisser un temps de réflexion à tou⋅te⋅s avant de prendre la parole peut être&nbsp;utile.</p>
|
||
</li>
|
||
<li>
|
||
<p>Inclusion des personnes trans et non-binaires : Faire un tour des pronoms peut permettre aux personnes trans et non-binaires d&#8217;être plus incluses, ou en tout cas de visibiliser leur présence. On ne l&#8217;avait pas fait lors du premier jour et ça à manqué&nbsp;;</p>
|
||
</li>
|
||
<li>
|
||
<p>Sur un plan plus pragmatique, trouver une logistique pour faire à manger de manière collective / faire le ménage / installer les tables etc, pourrait permettre aux organisateur⋅ice⋅s de participer aux&nbsp;discussions.</p>
|
||
</li>
|
||
<li>
|
||
<p>Lors de la phase d&#8217;organisation, il est possible de fusionner les sujets, et ça à été le cas pour au moins deux sujets proposés, ce qui à créé une situations problématique. Dans son livre qui parle des forums ouverts, Owen indique que parfois il vaut mieux ne pas fusionner les sujets, et je pense qu&#8217;on aurait sûrement du ici. Les attentes des participant⋅e⋅s ne sont pas forcement les mêmes, et ça peut créer de la frustration si les choses ne sont pas forcément bien amenées. C&#8217;est sûrement quelque chose à souligner aux participant⋅e⋅s lors du temps&nbsp;d&#8217;accueil.</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="animer-etou-participer">Animer et/ou participer&nbsp;?</h2>
|
||
<p>A titre personnel, j&#8217;ai été assez frustré par la posture un peu floue que j&#8217;avais durant le forum : je faisais partie de l&#8217;équipe d&#8217;organisation mais je ne m&#8217;occupais pas de l&#8217;animation, nourrissant l&#8217;espoir de participer aux&nbsp;discussions.</p>
|
||
<p>J&#8217;ai pu participer à certaines discussions, mais jamais (sauf une exception) pour une session entière, et j&#8217;ai trouvé ça dommage. Après une discussion avec Thomas qui à déjà animé au moins un forum ouvert, il semble possible d&#8217;« ouvrir » et de « fermer » les temps d&#8217;organisation, pour permettre aux organisateur⋅ice⋅s d&#8217;animer et de&nbsp;participer.</p>
|
||
<p>J&#8217;aime bien cette idée, parce que ça veut dire que tout le monde peut participer, et que la posture d&#8217;animation ne signifie pas un « sacrifice », mais peut-être que cette idée à aussi ses défauts : lors d&#8217;une discussion avec un⋅e des animateurs⋅rices iel m&#8217;a indiqué qu&#8217;iel préférait rester extérieur aux discussions, pour éviter les prises de&nbsp;pouvoir.</p>
|
||
<p>Autrement dit, faire l&#8217;animation du forum ouvert conférerait un pouvoir qui pourrait être néfaste lors des discussions. Je ne sais pas trop quoi penser de cette idée, mais il me semble pertinent de pousser la réflexion. Dans une posture plus « classique » de facilitation, on s&#8217;efforce de rester extérieur aux discussions, pour ne pas avoir de conflit&nbsp;d&#8217;intérêt.</p>
|
||
<p>Mais dans le cas du forum ouvert, je n&#8217;ai pas l&#8217;impression que faire l&#8217;animation confère un pouvoir sur le groupe, autre que celui d&#8217;être garant⋅e des règles du fonctionnement collectif (rappel de l&#8217;heure par exemple, rappel du cadre de bienveillance). Si vous avez des retours sur ce sujet je suis preneur&nbsp;!</p>
|
||
<p>Voire, je me demande même quel rapports cela génère de — justement — rester extérieur et de ne pas participer, alors même qu&#8217;on est présent⋅e. Dit autrement, alors que tout le monde se rencontre à travers les discussions, se met en jeu, ce n&#8217;est pas le cas des animateur⋅ice⋅s, et je me demande si ça impacte l&#8217;ambiance générale&nbsp;?</p>
|
||
<p>En tout cas, j&#8217;aime bien l&#8217;idée qu&#8217;il soit possible d&#8217;à la fois animer les temps de forums et de participer. Dans ce cas là, existe-il des stratagèmes / artifices pour permettre de visibiliser ces prises de pouvoir pendant les discussions&nbsp;?</p>
|
||
<p>Je suis preneur de tout retour d&#8217;expérience sur le sujet&nbsp;!</p></content><category term="journal"></category></entry><entry><title>Artfevre 2020 - Défi artistique en février</title><link href="https://blog.notmyidea.org/artfevre-2020-defi-artistique-en-fevrier.html" rel="alternate"></link><published>2020-03-01T00:00:00+01:00</published><updated>2020-03-01T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-03-01:/artfevre-2020-defi-artistique-en-fevrier.html</id><summary type="html"><p>En Février, il y a 29 Jours, et avec un ami on s&#8217;est dit qu&#8217;on aimerait bien utiliser chacun d&#8217;entre eux pour créer — de manière intensive et sans jugement — hors de notre zone de confort, et avec des contraintes&nbsp;imposées.</p>
|
||
<p>L&#8217;idée, c&#8217;est qu&#8217;à la …</p></summary><content type="html"><p>En Février, il y a 29 Jours, et avec un ami on s&#8217;est dit qu&#8217;on aimerait bien utiliser chacun d&#8217;entre eux pour créer — de manière intensive et sans jugement — hors de notre zone de confort, et avec des contraintes&nbsp;imposées.</p>
|
||
<p>L&#8217;idée, c&#8217;est qu&#8217;à la fin du mois, chacun⋅e puisse se retourner (c&#8217;est une image hein) et se dire : « Ouah, j’ai fait tout ça !?&nbsp;»</p>
|
||
<p>C’est donc une une liste de 29 thèmes (un par jour du mois) : chaque jour, on doit faire quelque chose d’artistique à partir du thème&nbsp;proposé.</p>
|
||
<h2 id="quelques-retours">Quelques&nbsp;retours</h2>
|
||
<p>Je n&#8217;ai pas réussi à faire des créations pour les 29 thèmes, mais dans l&#8217;ensemble je suis très content de ce que j&#8217;ai pu créer : j&#8217;ai pu expérimenter des choses que je n&#8217;avais pas imaginées. J&#8217;ai pu faire&nbsp;:</p>
|
||
<ul>
|
||
<li>Du montage vidéo&nbsp;;</li>
|
||
<li>De la musique acoustique&nbsp;;</li>
|
||
<li>De la musique électronique&nbsp;;</li>
|
||
<li>Du montage audio&nbsp;;</li>
|
||
<li>De l&#8217;écriture de nouvelles&nbsp;;</li>
|
||
<li>Une comptine&nbsp;;</li>
|
||
<li>De la photo&nbsp;;</li>
|
||
<li>Du montage photo&nbsp;;</li>
|
||
<li>De l&#8217;Art Plastique&nbsp;;</li>
|
||
</ul>
|
||
<p>C&#8217;était très sympa de voir les créations des unes et des uns arriver sur notre espace de partage de fichiers, certaines créations étaient vraiment géniales ! Et j&#8217;ai même carrément hâte de remettre ça l&#8217;an prochain&nbsp;:-)</p>
|
||
<h2 id="un-peu-plus-dinfos">Un peu plus&nbsp;d&#8217;infos</h2>
|
||
<p>Voici des infos qu&#8217;on a envoyé aux participant⋅e⋅s, et que je consigne ici question de l&#8217;avoir quelque&nbsp;part</p>
|
||
<p>Voici une liste d&#8217;idées de « trucs » à faire chaque jour : Faire un dessin, Composer (et enregistrer ?) une musique, Filmer quelque chose, Inventer une chorégraphie, Écrire un texte, Inventer une origami, Se faire un tatouage (en fonction du thème, pas conseillé), Inventer un exercice de théâtre, Créer un jeu, Faire une sculpture d’argile, Créer une position de Yoga, Prendre une photo, inventer une recette de cuisine, Écrire un slam, etc,&nbsp;etc.</p>
|
||
<p>Vous pouvez décider de ne choisir qu’une forme artistique (par exemple que la musique) pour vous forcer à explorer un médium en dehors de votre zone de confort (« je sais faire une musique rapidement, mais sais-je faire 29 fois une musique différente rapidement ? »), ou alors changer d’expression artistique tous les jours. Voyez ce qui vous amuse / anime le plus&nbsp;!</p>
|
||
<p>On aimerait mettre en commun nos productions quelque part, pour voir comment les gens différents se sont approprié un même thème ! Bien sur c&#8217;est tout à fait optionnel : libre à vous de participer sans publier vos&nbsp;créations.</p>
|
||
<p>Ça vous botte ? Envoyez nous un petit mail a artfevre@notmyidea.org et on vous tient au courant !
|
||
Techniquement&nbsp;?</p>
|
||
<p>Si vous voulez poster vos créations, on vous propose de le faire sur un espace en ligne. Plusieurs choses sur ce « cloud »&nbsp;:</p>
|
||
<ul>
|
||
<li>
|
||
<p>On a préparé un dossier par jour, postez votre / vos création(s) dans le dossier qui va bien. Il y a également un dossier « Les thèmes <span class="amp">&amp;</span> ressources » qui contient les photos, vidéos et musiques qui serviront de contraintes certains jours, ainsi qu&#8217;un rappel des thèmes&nbsp;;</p>
|
||
</li>
|
||
<li>
|
||
<p>On a aucun moyen de savoir qui poste quoi, si vous voulez être crédités, mettez votre pseudo / nom dans le nom du fichier (ex. « Sam-3-fevrier.jpg » ou « AlexCompo7Fevrier.mp3 »). Si vous préférez l&#8217;ombre à la lumière, vous pouvez laisser un titre poétique comme «W33.jpg »&nbsp;;</p>
|
||
</li>
|
||
<li>
|
||
<p>Ne repostez pas les contenus d&#8217;autres participant⋅es (d&#8217;aucun diraient « d&#8217;autrui ») sans leur accord&nbsp;;</p>
|
||
</li>
|
||
</ul>
|
||
<p>Pour avoir l&#8217;adresse du cloud magique, envoyez nous un mail à&nbsp;artfevre@notmyidea.org.</p>
|
||
<h2 id="invitations">Invitations</h2>
|
||
<p>Le défi commence le samedi 1er Février, mais il est possible de nous rejoindre en route : si vous voulez en parler à des ami⋅e⋅s, n&#8217;hésitez pas&nbsp;!</p>
|
||
<p>Donnez leur l&#8217;adresse du site web :&nbsp;https://artfevre.notmyidea.org</p>
|
||
<h2 id="rappels">Rappels</h2>
|
||
<p>Pas de pression : Amusons-nous, l&#8217;idée est de passer de bons&nbsp;moments</p>
|
||
<ul>
|
||
<li>Je ne veux faire qu&#8217;une seule semaine ? Pas de soucis&nbsp;!</li>
|
||
<li>J&#8217;ai pas envie de poser mes publications en public… No problem&nbsp;!</li>
|
||
<li>J&#8217;ai loupé trois jours, c&#8217;est la merde ! Hakuna Matata&nbsp;!</li>
|
||
<li>J&#8217;ai envie de faire un thème à plusieurs ! No problemo&nbsp;!</li>
|
||
</ul>
|
||
<p>Personne d&#8217;autre que vous ne juge ce que vous faites ! Et… à propos de ça, même vous d&#8217;ailleurs n&#8217;y êtes pas&nbsp;obligés.</p>
|
||
<h2 id="des-questions-des-reponses">Des questions ? Des réponses&nbsp;!</h2>
|
||
<h3 id="jai-envie-de-le-faire-mais-je-suis-trop-perfectionniste-pour-finir-un-truc-par-jour">J’ai envie de le faire, mais je suis trop perfectionniste pour finir un truc par jour&nbsp;!</h3>
|
||
<p>C’est tout le sens du projet ! Si je dois finir cette chanson/ce dessin/ce texte aujourd’hui, ça ne sera peut-être pas le meilleur des dessins, mais au moins il aura le mérite d’exister. Dans mon expérience personnelle, si j’attends d’avoir produit le meilleur objet, je finis par ne rien finir, car rien n’est parfait. Là, au moins, l’objet existe, et si vous le souhaitez, il peut servir de base plus tard à un re-travail pour viser quelque chose de plus « fignolé&nbsp;».</p>
|
||
<h3 id="mais-si-je-rate-un-jour-si-jai-pas-le-temps">Mais si je rate un jour, si j’ai pas le temps&nbsp;?</h3>
|
||
<p>Chacun⋅e fait comme iel veut/peut et s’astreint la discipline qu’iel a envie de tester ! Personne ne viendra surveiller ou juger le travail des autres. Si vous prenez 2 jours par thème et que vous continuez le truc jusqu’à fin mars pour finir, pas de soucis&nbsp;!</p>
|
||
<h3 id="jai-peur-de-pas-avoir-linspiration">J’ai peur de pas avoir l’inspiration&nbsp;!</h3>
|
||
<p>Pour nous, attendre l’inspiration est un prétexte qu&#8217;on se donne pour repousser le moment de se mettre au travail. L’inspiration, ça se provoque, ça ne s’attend pas. Et puis peut-être que je trouverai nulle ma création du jour, mais au moins j’aurai fait quelque chose. 1 vaut mieux que 0. Et de ce truc que moi je trouve nul (c’est pas pour ça que c’est nul, à vrai dire), peut-être que j&#8217;en tirerai une note que j’aime bien, une formulation qui me plaît, un mouvement que j’adore, et que je ré-utiliserai après dans une autre création. Ou alors, peut-être que je ne retirerai que la satisfaction de l’avoir fait, et c’est déjà pas mal&nbsp;!</p></content><category term="journal"></category></entry><entry><title>Le piège du développement personnel</title><link href="https://blog.notmyidea.org/le-piege-du-developpement-personnel.html" rel="alternate"></link><published>2020-01-21T00:00:00+01:00</published><updated>2020-01-21T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-01-21:/le-piege-du-developpement-personnel.html</id><summary type="html"><p>Ces derniers temps, je me suis retrouvé à questionner mon rapport a la pratique du développement personnel. À quel point le celui ci, et la « psychologie positive » peuvent-elles jouer un rôle de « cache misère » vis à vis des différentes formes d&#8217;oppression et de domination à l&#8217;œuvre dans notre …</p></summary><content type="html"><p>Ces derniers temps, je me suis retrouvé à questionner mon rapport a la pratique du développement personnel. À quel point le celui ci, et la « psychologie positive » peuvent-elles jouer un rôle de « cache misère » vis à vis des différentes formes d&#8217;oppression et de domination à l&#8217;œuvre dans notre société&nbsp;?</p>
|
||
<p>Voire même : ce courant de pensée peut-il favoriser un certain conservatisme ? Se changer soi même équivaut-il à une adaptation au système en place, supprimant alors toute volonté de révolte et de changement sociétal&nbsp;?</p>
|
||
<p>Face à un constat considéré comme « négatif » sur notre société, plusieurs manières de prendre la chose (entre autres)&nbsp;:</p>
|
||
<ol>
|
||
<li><strong>Le travail sur soi</strong>, qui cherche à percevoir les choses sous le meilleur angle possible. Ici, « Toute expérience est bonne à prendre »&nbsp;;</li>
|
||
<li><strong>La problématisation</strong> : essayer de comprendre quelles sont les normes et les valeurs qui amènent au problème&nbsp;constaté.</li>
|
||
</ol>
|
||
<h2 id="le-probleme">Le problème&nbsp;?</h2>
|
||
<p>« Travailler sur soi » est parfois mis en opposition avec le fait de déconstruire sociétalement notre&nbsp;monde.</p>
|
||
<p>Il est (bien sur) souhaitable de mieux vivre la violence des systèmes oppressifs, mais il semble quelque part important d&#8217;en avoir d&#8217;abord conscience, pour que ce « travail sur soi » ne soit pas assimilé à une « technique de l&#8217;autruche&nbsp;».</p>
|
||
<p>Il semble aussi que nous ne sommes malheureusement pas tou⋅te⋅s égaux/égales face aux violences systémiques, et « mieux vivre » ces violences, bien que possible pour certain⋅e⋅s, reste impossible pour d&#8217;autres <sup id="fnref:matrice-des-dominations"><a class="footnote-ref" href="#fn:matrice-des-dominations">1</a></sup>.</p>
|
||
<p>Plutôt que d&#8217;accepter (implicitement) cette violence, il me semble utile de <strong>comprendre comment cette violence s&#8217;applique</strong>, de manière à remonter aux racines du problème, pour pouvoir le&nbsp;résoudre.</p>
|
||
<h2 id="developpement-personnel-vs-sociologie">Développement personnel vs&nbsp;sociologie</h2>
|
||
<blockquote>
|
||
<p>N&#8217;acceptez pas les choses que vous ne pouvez changer, mais changez les choses que vous ne pouvez pas&nbsp;accepter. </p>
|
||
<p>— Angela&nbsp;Davis</p>
|
||
</blockquote>
|
||
<p>Le développement personnel, bien qu&#8217;une pratique avec des buts qui semblent nobles de prime abord, semble contenir son lot de&nbsp;problèmes.</p>
|
||
<p>Parmi ceux-cis : une minimisation des problèmes ressentis, et comme le dit Aude Vidal dans son livre « Égologie », une culpabilisation de chacun⋅e : « Si tu en est là, c&#8217;est que tu choisis de voir les choses sous cet angle&nbsp;».</p>
|
||
<blockquote>
|
||
<p>« Se changer soi pour changer le monde », cette prescription […] semble au final un leurre, car travailler sur soi-même […] c&#8217;est avant tout accepter une vision du monde où chacun⋅e étant capable d&#8217;aller bien, chacun⋅e est responsable de son sort.
|
||
— Aude Vidal,&nbsp;Égologie</p>
|
||
</blockquote>
|
||
<p>Parfois, on en vient également à « psychologiser » des situations, c&#8217;est à dire essayer d&#8217;expliquer des situations sociétales comme on le ferait d&#8217;une personne, sans prendre en compte la société dans son ensemble et dans sa complexité, et cela vient se substituer à l&#8217;approche&nbsp;sociologique.</p>
|
||
<p>On peut également voir ce déni de l&#8217;approche sociologique comme une naïveté à l&#8217;égard du monde, entretenue par les nombreux ouvrages qu&#8217;on trouve sur le sujet. On nous dira bientôt qu&#8217;il faut arrêter de se tenir au courant de ce qui se déroule dans le monde, les mauvaises nouvelles étant diablement mauvaises pour notre&nbsp;Karma.</p>
|
||
<p>Penser le monde dans sa complexité me semble une condition nécessaire pour pouvoir le faire évoluer dans une direction&nbsp;intéressante. </p>
|
||
<h2 id="une-culture-de-la-passivite">Une culture de la&nbsp;passivité</h2>
|
||
<p>Cette manière de penser le monde nous pousse à la passivité : si plutôt que de voir les choses en face, nous décidons de changer notre manière de percevoir les problèmes, alors nous nous&nbsp;dépolitisons.</p>
|
||
<p>Elle laisse également penser que l&#8217;approche sociologique nous empêcherait d&#8217;agir, comme si réfléchir aux problèmes de société était un problème en soi, alors que monopole de la résolution de conflit n&#8217;est pas au développement personnel&nbsp;!</p>
|
||
<p>L&#8217;approche sociologique permet quelque part de se déculpabiliser : on peut à partir du constat sociologique se dire « je suis oppréssé⋅e, c&#8217;est pas de ma faute, maintenant que je le sais je peux travailler dessus plus facilement&nbsp;».</p>
|
||
<p>Une prise de pouvoir, en quelque&nbsp;sorte.</p>
|
||
<h2 id="ressources-pour-aller-plus-loin">Ressources / pour aller plus&nbsp;loin</h2>
|
||
<ol>
|
||
<li><a href="https://www.monde-diplomatique.fr/2018/08/MALET/58981">Le système Pierre Rahbi — Le monde&nbsp;diplomatique</a></li>
|
||
<li><a href="https://blog.notmyidea.org/egologie.html">Égologie, par Aude&nbsp;Vidal</a></li>
|
||
<li><a href="https://labrique.net/index.php/thematiques/politicaille/954-cyril-dion-coli-briseur-de-l-ecologie-radicale">Cyril Dion, Coli-briseur de l&#8217;écologie radicale — La&nbsp;brique</a></li>
|
||
</ol>
|
||
<div class="footnote">
|
||
<hr>
|
||
<ol>
|
||
<li id="fn:matrice-des-dominations">
|
||
<p>Comme théorisé avec la <a href="https://en.wikipedia.org/wiki/Matrix_of_domination">matrice des dominations</a>.&#160;<a class="footnote-backref" href="#fnref:matrice-des-dominations" title="Jump back to footnote 1 in the text">&#8617;</a></p>
|
||
</li>
|
||
</ol>
|
||
</div></content><category term="journal"></category></entry><entry><title>Packager du python pour Debian</title><link href="https://blog.notmyidea.org/packager-du-python-pour-debian.html" rel="alternate"></link><published>2020-01-14T00:00:00+01:00</published><updated>2020-01-14T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-01-14:/packager-du-python-pour-debian.html</id><summary type="html">
|
||
<p>Aujourd&#8217;hui j&#8217;ai fais un peu de packaging pour la distribution Linux Debian, avec l&#8217;aide d&#8217;un ami. C&#8217;était assez agréable de pouvoir me faire aider dans cet objectif : j&#8217;avais déjà tenté l&#8217;expérience en solo par le passé, et m&#8217;étais cassé les dents sur …</p></summary><content type="html">
|
||
<p>Aujourd&#8217;hui j&#8217;ai fais un peu de packaging pour la distribution Linux Debian, avec l&#8217;aide d&#8217;un ami. C&#8217;était assez agréable de pouvoir me faire aider dans cet objectif : j&#8217;avais déjà tenté l&#8217;expérience en solo par le passé, et m&#8217;étais cassé les dents sur le&nbsp;sujet.</p>
|
||
<p>Voici quelques notes prises durant l&#8217;après-midi, qui pourront sans doute me servir pour la&nbsp;suite.</p>
|
||
<h2 id="quest-ce-quon-fait">Qu&#8217;est-ce qu&#8217;on fait&nbsp;?</h2>
|
||
<p>On essaye de créer un paquet Debian pour une application Web écrite en python. Il s&#8217;agit d&#8217;une application assez simple, qui communique avec une base de données d&#8217;un côté, et avec des utilisateurs de&nbsp;l&#8217;autre.</p>
|
||
<h2 id="y-aller-par-etapes">Y aller par&nbsp;étapes</h2>
|
||
<p>On a essayé de faire en sorte d&#8217;avoir quelque chose de fonctionnel assez rapidement, même si pas entièrement fait dans les règles de l&#8217;art. Ça à l&#8217;avantage de garder la motivation&nbsp;:-)</p>
|
||
<ol>
|
||
<li>Produire un paquet <code>.deb</code> qui peut s&#8217;installer, et qui fait tourner l&#8217;application en question&nbsp;;</li>
|
||
<li>Avoir un paquet qui passe les règles de validation de Debian&nbsp;;</li>
|
||
<li>Intégrer le paquet avec <code>systemd</code> ;</li>
|
||
<li>Intégrer le paquet dans un système de contrôle de version type git&nbsp;;</li>
|
||
</ol>
|
||
<h2 id="packaging-simple-1ere-version-fonctionnelle">Packaging « simple » - 1ère version&nbsp;fonctionnelle</h2>
|
||
<p>On commence par faire un paquet dit « natif ». C&#8217;est l&#8217;approche la plus simple.
|
||
Deux fichiers sont importants, pour commencer : <code>control</code> et <code>changelog</code>. Le fichier <code>control</code> contient un bloc « source » et un ou plusieurs blocs « package », dans l&#8217;idée de pouvoir avoir potentiellement plusieurs paquets binaires générés à partir du même package source, ce qui est utile pour les gros&nbsp;paquets.</p>
|
||
<p>Voici les étapes qu&#8217;on a suivi&nbsp;:</p>
|
||
<ol>
|
||
<li>Créer les fichiers <code>control</code>, <code>changelog</code> et <code>rules</code> dans le répertoire <code>debian</code>. Dans la pratique on peut les copier depuis un autre paquet qu&#8217;on prends comme modèle&nbsp;;</li>
|
||
<li>Installer les dépendances de build avec <code>sudo apt install devscripts &amp;&amp; mk-build-deps -i -r --root-cmd sudo</code> ;</li>
|
||
<li>Lancer <code>dpkg-buildpackage -rfakeroot</code> qui va construire le paquet pour nous&nbsp;;</li>
|
||
<li>Regarder la sortie de la commande pour voir les dépendances qui ne sont pas déjà prêtes pour Debian&nbsp;;</li>
|
||
<li>Pour les quelques dépendances qui n&#8217;étaient pas déjà prêtes, on a répété les étapes&nbsp;précédentes.</li>
|
||
</ol>
|
||
<h2 id="questions-diverses-observations">Questions diverses <span class="amp">&amp;</span>&nbsp;observations</h2>
|
||
<p><code>dh-helper</code> est une manière de packager « officiellement recommandée », il s&#8217;agit d&#8217;un ensemble d&#8217;outils qui cherchent à se faciliter la tache de <em>packaging</em>.</p>
|
||
<p>Pour les traductions : il n&#8217;est pas nécessaire de faire des paquets séparés pour la traduction, c&#8217;est acceptable de tout mettre dans le même&nbsp;paquet.</p>
|
||
<p>La documentation peut elle aussi être intégrée dans le même&nbsp;paquet.</p>
|
||
<p>Pour les numéros de version, si on a pas de tiret dans le numéro de version, alors il s&#8217;agit de la version <em>upstream</em>. Si on a un tiret, ce qui est après le numéro de version est la version du <em>packaging</em> pour&nbsp;Debian.</p>
|
||
<p><code>DEB_BUILD_OPTIONS=nocheck</code> permet de ne pas avoir à lancer les tests à chaque fois qu&#8217;on construit le&nbsp;paquet.</p>
|
||
<h2 id="etapes-dapres">Étapes&nbsp;d&#8217;après</h2>
|
||
<ul>
|
||
<li>Peut-être utiliser<code>debian/missing-sources</code>, en tout cas régler le souci pour les bibliothèques JavaScript et le <span class="caps">CSS</span> dont les sources ne sont pas distribuées actuellement (parce que versions&nbsp;minifiées).</li>
|
||
<li>Il est possible d&#8217;installer des dépendances et de spécifier des liens symboliques à créer lors de&nbsp;l&#8217;installation.</li>
|
||
<li>Intégrer de la documentation sous forme de <code>manpage</code>. Il semble que certains outils permettent de le faire de manière simple / automatique, comme « help2man&nbsp;»</li>
|
||
<li>De la même manière qu&#8217;on le fait pour les ressources type <span class="caps">JS</span> et <span class="caps">CSS</span>, il faut intégrer les <em>fonts</em>, en faisant référence aux fonts empaquetées pour&nbsp;Debian. </li>
|
||
<li>Une fois que tout ça fonctionne, passer à un système de build qui comprends&nbsp;git</li>
|
||
<li>Faire une intégration avec <code>systemd</code> pour avoir un service qui se lance automatiquement. Ce qui veut aussi dire créer un utilisateur spécifique pour notre&nbsp;service.</li>
|
||
</ul></content><category term="notes"></category></entry><entry><title>Prendre le temps</title><link href="https://blog.notmyidea.org/prendre-le-temps.html" rel="alternate"></link><published>2020-01-14T00:00:00+01:00</published><updated>2020-01-14T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-01-14:/prendre-le-temps.html</id><summary type="html"><h2 id="prendre-le-temps">Prendre le&nbsp;temps</h2>
|
||
<p>Jusqu&#8217;ici, j&#8217;ai souvent eu l&#8217;impression que le temps s&#8217;écoulait sans que je puisse avoir de prise&nbsp;dessus.</p>
|
||
<p>Depuis peu, je me rends compte que j&#8217;ai l&#8217;opportunité de « visiter » ce flux, de — quelque part — « naviguer » en son sein, et que ce faisant …</p></summary><content type="html"><h2 id="prendre-le-temps">Prendre le&nbsp;temps</h2>
|
||
<p>Jusqu&#8217;ici, j&#8217;ai souvent eu l&#8217;impression que le temps s&#8217;écoulait sans que je puisse avoir de prise&nbsp;dessus.</p>
|
||
<p>Depuis peu, je me rends compte que j&#8217;ai l&#8217;opportunité de « visiter » ce flux, de — quelque part — « naviguer » en son sein, et que ce faisant, il se densifie, il prends plus de place, il s&#8217;épaissit en quelque&nbsp;sorte.</p>
|
||
<p>Je prends plus de temps pour ressentir ce que je fais, et les effets semblent également se sentir sur ma relation aux autres, et sur le soin que je veux porter à mes&nbsp;relations.</p>
|
||
<p>Ça me donne l&#8217;impression d&#8217;avoir un contrôle sur le temps qui s&#8217;écoule (et ça c&#8217;est cool&nbsp;:-)).</p></content><category term="journal"></category></entry><entry><title>Limites horaires</title><link href="https://blog.notmyidea.org/limites-horaires.html" rel="alternate"></link><published>2020-01-04T00:00:00+01:00</published><updated>2020-01-04T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-01-04:/limites-horaires.html</id><summary type="html">
|
||
<p>Depuis que j&#8217;ai décidé de faire un break technologique, je ne m&#8217;en sors pas si mal. Parmi les mesures que j&#8217;avais envie de prendre, était le fait de limiter le temps d&#8217;utilisation de mon ordinateur&nbsp;personnel.</p>
|
||
<p>J&#8217;utilise le logiciel <a href="https://launchpad.net/timekpr-next">timekpr-next</a> qui me permet de définir …</p></summary><content type="html">
|
||
<p>Depuis que j&#8217;ai décidé de faire un break technologique, je ne m&#8217;en sors pas si mal. Parmi les mesures que j&#8217;avais envie de prendre, était le fait de limiter le temps d&#8217;utilisation de mon ordinateur&nbsp;personnel.</p>
|
||
<p>J&#8217;utilise le logiciel <a href="https://launchpad.net/timekpr-next">timekpr-next</a> qui me permet de définir une limite d&#8217;utilisation par jour. Le logiciel me notifie quand je dois m&#8217;arrêter, et même si je peux rajouter du temps si j&#8217;en ai besoin, ça semble plutôt marcher : ça me donne un moyen de percevoir le temps que je dépense derrière cet&nbsp;ordinateur.</p></content><category term="journal"></category></entry><entry><title>Prendre soin</title><link href="https://blog.notmyidea.org/prendre-soin.html" rel="alternate"></link><published>2020-01-04T00:00:00+01:00</published><updated>2020-01-04T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-01-04:/prendre-soin.html</id><summary type="html">
|
||
<p><em>De moi, et de ma relation aux&nbsp;autres.</em></p>
|
||
<p>C&#8217;est peut-être l&#8217;effet des deux semaines de vacances : je me retrouve à prendre plus soin de mes relations aux autres humain⋅e⋅s, à avoir plus d&#8217;empathie, et j&#8217;ai l&#8217;impression de tisser des liens plus forts avec …</p></summary><content type="html">
|
||
<p><em>De moi, et de ma relation aux&nbsp;autres.</em></p>
|
||
<p>C&#8217;est peut-être l&#8217;effet des deux semaines de vacances : je me retrouve à prendre plus soin de mes relations aux autres humain⋅e⋅s, à avoir plus d&#8217;empathie, et j&#8217;ai l&#8217;impression de tisser des liens plus forts avec les personnes que je&nbsp;croise.</p>
|
||
<p>C&#8217;est agréable&nbsp;:-)</p></content><category term="journal"></category></entry><entry><title>Remettre les choses à plus tard</title><link href="https://blog.notmyidea.org/remettre-les-choses-a-plus-tard.html" rel="alternate"></link><published>2020-01-04T00:00:00+01:00</published><updated>2020-01-04T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2020-01-04:/remettre-les-choses-a-plus-tard.html</id><summary type="html">
|
||
<p>Une autre astuce qui me permet de retrouver du temps, c&#8217;est de remettre certaines choses à plus tard. Certain⋅ne⋅s diraient que c&#8217;est de la procrastination, mais je demande par exemple aux personnes de passer par les canaux qui me permettent de mieux compartimenter les&nbsp;choses.</p>
|
||
<p>Par …</p></summary><content type="html">
|
||
<p>Une autre astuce qui me permet de retrouver du temps, c&#8217;est de remettre certaines choses à plus tard. Certain⋅ne⋅s diraient que c&#8217;est de la procrastination, mais je demande par exemple aux personnes de passer par les canaux qui me permettent de mieux compartimenter les&nbsp;choses.</p>
|
||
<p>Par exemple, si je reçois un <span class="caps">SMS</span> qui me demande de faire quelque chose en rapport avec la technologie, je demande à la personne émettrice de m&#8217;envoyer un&nbsp;email.</p></content><category term="journal"></category></entry><entry><title>Break technologique</title><link href="https://blog.notmyidea.org/break-technologique.html" rel="alternate"></link><published>2019-12-14T00:00:00+01:00</published><updated>2019-12-14T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-12-14:/break-technologique.html</id><summary type="html"><p>Comme je le soulignais il y a quelques jours dans ce journal de bord, je suis « drogué aux écrans ». Au point que je passe parfois ma journée entière sans en décrocher, en passant de l&#8217;un à&nbsp;l&#8217;autre.</p>
|
||
<h2 id="les-problemes">Les&nbsp;problèmes</h2>
|
||
<p>En fait, en analysant un peu plus la situation …</p></summary><content type="html"><p>Comme je le soulignais il y a quelques jours dans ce journal de bord, je suis « drogué aux écrans ». Au point que je passe parfois ma journée entière sans en décrocher, en passant de l&#8217;un à&nbsp;l&#8217;autre.</p>
|
||
<h2 id="les-problemes">Les&nbsp;problèmes</h2>
|
||
<p>En fait, en analysant un peu plus la situation, et en ciblant les <em>usages</em> plutôt que les <em>objets</em>, je me rends compte que je suis drogué à plusieurs choses&nbsp;:</p>
|
||
<h3 id="immediatete-des-communications">Immédiateté des&nbsp;communications</h3>
|
||
<p>Que ce soit les emails, que je vais consulter plusieurs fois par jour (quand ce n&#8217;est pas en continu) ou les notifications instantanées (Signal, Whatsapp, Messenger etc), je me retrouve souvent derrière l&#8217;écran pour les&nbsp;lire.</p>
|
||
<p>Avec un effet de bord assez étrange : parfois je souhaite simplement envoyer un mail à quelqu&#8217;un·e, et en ouvrant mon client mail je me retrouve à… tout simplement oublier, plongé dans le flux des mails reçus et à&nbsp;traiter.</p>
|
||
<h3 id="dependance-aux-notifications-web">Dépendance aux notifications&nbsp;Web</h3>
|
||
<p>Que ce soit sur le réseau social « Mastodon », sur lequel je ne publie pas grand chose, mais que j&#8217;actualise parfois de manière frénétique pour « savoir ce qui s&#8217;y raconte », ou sur des site tels que Le bon coin, Github, ou Youtube, je me retrouve à « lire le flux », sans trop réussir à en sortir.&nbsp;Aspiré.</p>
|
||
<h3 id="le-sweet-spot-du-dev">Le « Sweet Spot » du&nbsp;dev</h3>
|
||
<p>Parfois, je code, et quand ça m&#8217;arrive, je suis dans une sorte de transe assez incroyable, durant laquelle pendant plusieurs heures je ne fais rien d&#8217;autre, parfois même sans manger ni bouger du canapé : il faut que je termine&nbsp;!</p>
|
||
<p>C&#8217;est à la fois quelque chose de « bien » parce que je progresse et les outils sur lesquels je bossent fonctionnent, mais c&#8217;est au détriment bien sur d&#8217;un équilibre de mon&nbsp;quotidien&#8230;</p>
|
||
<h2 id="pistes-pour-men-sortir">Pistes pour m&#8217;en&nbsp;sortir</h2>
|
||
<p>J&#8217;ai l&#8217;impression que je peux trouver des pistes de solution à la fois techniques (technologiques) et à la fois liées à mon mode de&nbsp;vie.</p>
|
||
<h3 id="solutions-technologiques">Solutions&nbsp;technologiques</h3>
|
||
<p>En écrivant tout ça, je me dis plusieurs choses&nbsp;:</p>
|
||
<ul>
|
||
<li>Je devrais me désinscrire des services de communication type Whatsapp et&nbsp;Signal.</li>
|
||
<li>Je devrais limiter drastiquement les applications installées sur mon téléphone (plus de mails, youhou&nbsp;!)</li>
|
||
<li>Existe-il un moyen (Thunderbird ?) d&#8217;écrire des mails sans voir sa liste de mails&nbsp;?</li>
|
||
</ul>
|
||
<h3 id="solutions-liees-a-mon-mode-de-vie">Solutions liées à mon mode de&nbsp;vie</h3>
|
||
<p>Mais… Il me semble que c&#8217;est surtout une question de volonté et « d&#8217;hygiène numérique » : si je me demande quelle place je veux laisser aux écrans dans ma vie, alors je doit questionner l&#8217;usage que j&#8217;en&nbsp;ait.</p>
|
||
<ul>
|
||
<li>Je peux limiter le nombre d&#8217;outils que j&#8217;utilise au&nbsp;quotidien.</li>
|
||
<li>Est-ce que je peux me passer d&#8217;un smartphone&nbsp;?</li>
|
||
<li>Est-ce que je peux me passer d&#8217;une connexion internet ? Au travail ? Chez moi&nbsp;?</li>
|
||
</ul>
|
||
<p>Est-ce que je ne devrais pas simplement « arrêter de faire de l&#8217;informatique », au moins pour un temps ? Ça aurait le mérite de me permettre de me désengager de certains projets qui ont des liens forts avec le numérique, et qui parfois pourrissent mon&nbsp;quotidien.</p>
|
||
<p>Des solutions radicales, mais je me posais déjà des questions similaires dans <a href="https://blog.notmyidea.org/focusing-on-what-matters.html">un article de 2016 (en anglais)</a>, sans avoir vraiment réussi à m&#8217;y&nbsp;tenir.</p>
|
||
<blockquote>
|
||
<ul>
|
||
<li>Check emails only once a day. Do not do it in the morning, before working, to keep my mind clear. I would say at 2pm (after lunch). (This doesn&#8217;t mean I will not send mails&nbsp;tho)</li>
|
||
<li>Stay away from the Internet during the morning. I&#8217;ll not connect if I don&#8217;t need&nbsp;to.</li>
|
||
</ul>
|
||
</blockquote>
|
||
<h2 id="extinction-des-feux">Extinction des&nbsp;feux</h2>
|
||
<p>Voici une petite liste des choses qui semblent pouvoir réduire ma dépendance technologique&nbsp;:</p>
|
||
<ul>
|
||
<li><a href="https://github.com/spiral-project/ihatemoney/issues/517">Me détacher de la maintenance de ihatemoney</a>&nbsp;; </li>
|
||
<li>Supprimer la plupart des applications sur mes téléphones (pro et&nbsp;perso)</li>
|
||
<li>Éteindre mon serveur personnel&nbsp;;</li>
|
||
<li>Ne plus ramener mon téléphone pro à la maison&nbsp;;</li>
|
||
<li>Avoir un ordinateur fixe au travail, et l&#8217;y laisser&nbsp;;</li>
|
||
<li>Limiter mon utilisation de l&#8217;ordinateur perso à 1h par jour, sauf exceptions&nbsp;;</li>
|
||
<li>Aller voir mes emails pro une fois par jour uniquement&nbsp;;</li>
|
||
<li>Répondre au téléphone une fois par jour uniquement (et faire en sorte que mes correspondants&nbsp;comprennent);</li>
|
||
</ul>
|
||
<p>L&#8217;avenir dira ce que j&#8217;en fais, mais je suis content d&#8217;écrire ça&nbsp;:-)</p></content><category term="journal"></category></entry><entry><title>Assurance chômage</title><link href="https://blog.notmyidea.org/assurance-chomage.html" rel="alternate"></link><published>2019-12-13T00:00:00+01:00</published><updated>2019-12-13T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-12-13:/assurance-chomage.html</id><summary type="html">
|
||
<p>Depuis une génération, les durées et les montants d&#8217;indemnisation ont régulièrement diminué en France, par étapes successives, ce qui fait que bon nombre de salariés n&#8217;ont pas conscience qu&#8217;il ne seront indemnisés à 57 % de leur ex-salaire en cas de chômage, et pour seulement deux ans, alors …</p></summary><content type="html">
|
||
<p>Depuis une génération, les durées et les montants d&#8217;indemnisation ont régulièrement diminué en France, par étapes successives, ce qui fait que bon nombre de salariés n&#8217;ont pas conscience qu&#8217;il ne seront indemnisés à 57 % de leur ex-salaire en cas de chômage, et pour seulement deux ans, alors que les personnes de la génération précédente l&#8217;on été pendant trois ans à 75 % ou 80 % de leur&nbsp;ex-salaire. </p>
|
||
<p>Évolution des durées max d&#8217;indemnisations :
|
||
- 1979 : 36 mois
|
||
- 1984 : 30 mois
|
||
- 2001 : 23&nbsp;mois</p>
|
||
<h2 id="dates-cles-et-evolution">Dates clés et&nbsp;évolution</h2>
|
||
<ul>
|
||
<li><strong>Avant 1982</strong> l&#8217;indemnisation générale est de <strong>90 % du salaire brut</strong>.</li>
|
||
<li><strong>1982</strong> il y a un déficit, lié à une forte hausse du chômage (après le second choc pétrolier de&nbsp;1979)</li>
|
||
<li><strong>1982</strong>, hausse des cotisations, baisse des indemnisations et nouveau système les faisant dépendre de la durée de&nbsp;cotisation.</li>
|
||
<li><strong>1984</strong>, <strong>l&#8217;assistance de l&#8217;État suppléé l&#8217;Unédic</strong> pour les chômeurs en fin de droit., via l&#8217;<span class="caps">ASS</span> (l&#8217;allocation spécifique de&nbsp;solidarité),</li>
|
||
<li><strong>1988</strong> : Instauration du <span class="caps">RMI</span> (revenu minimum d&#8217;insertion) sous Michel&nbsp;Rocard.</li>
|
||
<li><strong>1992</strong> : Suite à une crise financière de l&#8217;Unédic, mesures d&#8217;économie :<ul>
|
||
<li>allongement de la durée de cotisation minimum (modifiée plusieurs&nbsp;fois)</li>
|
||
<li>dégressivité des&nbsp;allocations</li>
|
||
<li>contrôle renforcé de la recherche&nbsp;d&#8217;emploi.</li>
|
||
</ul>
|
||
</li>
|
||
<li><strong>2001</strong> : Le <span class="caps">MEDEF</span> impose la création du <span class="caps">PARE</span> (Plan d&#8217;aide au retour à l&#8217;emploi), et une forte baisse des&nbsp;cotisations.</li>
|
||
<li><strong>2002</strong> : Remontée du taux de chômage. La durée d&#8217;indemnisation passe de 30 à 23 mois et durcit les conditions d&#8217;accès au régime. Désormais, à peine la moitié des chômeurs sont indemnisés par&nbsp;l&#8217;Unédic.</li>
|
||
<li><strong>2006</strong> : Nouvelle convention qui durcit de nouveau les conditions d&#8217;accès au régime d&#8217;indemnisation, tout en instaurant le principe du guichet unique et le suivi mensuel des&nbsp;chômeurs.</li>
|
||
<li><strong>2009</strong> : Fusion Assedic + <span class="caps">ANPE</span> = Pôle&nbsp;emploi.</li>
|
||
<li><strong>2019</strong> : Nouvelle réforme de l&#8217;assurance chômage (Gouvernement&nbsp;Macron)</li>
|
||
</ul>
|
||
<p>Le régime de l&#8217;Assurance chômage est en constant déficit depuis 2009. Pour cette raison, sa dette atteint près de 26 milliards d&#8217;euros fin&nbsp;2015. </p>
|
||
<h2 id="evolution-du-taux-de-chomage">Évolution du taux de&nbsp;chômage</h2>
|
||
<p>Deux graphiques, qui montrent l&#8217;évolution du taux de chômage. Durant les périodes représentées ici, les conditions pour être « ayants-droit » ont&nbsp;évoluées. </p>
|
||
<p><img alt="Personnes considérées en recherche d'emploi" src="/images/chomage/taux-chomage.png"></p>
|
||
<p>Ce second graphique montre les personnes qui se considèrent en recherche d&#8217;emploi. On voir qu&#8217;il y a un écart important entre les deux&nbsp;graphiques.</p>
|
||
<p><img alt="Personnes qui se disent en recherche d'emploi" src="/images/chomage/halo-chomage.png"></p>
|
||
<p><a href="https://www.insee.fr/fr/statistiques/4201123#graphique-chomage-g1-fr">sources</a></p>
|
||
<h2 id="budget-de-lassurance-chomage">Budget de l&#8217;assurance&nbsp;chômage</h2>
|
||
<p><img alt="Budget dette" src="/images/chomage/dette-chomage.png"></p>
|
||
<h2 id="financement-de-lassurance-chomage">Financement de l&#8217;assurance&nbsp;chômage</h2>
|
||
<p>Les allocations chômage sont principalement financées par des cotisations prélevées sur les salaires. Les cotisations des employeurs représentent 4,05% des salaires&nbsp;bruts.</p>
|
||
<p>L&#8217;État participe également au financement, via l&#8217;impôt : depuis janvier 2019, une fraction de la &#8220;<span class="caps">CSG</span> activité&#8221; est affectée à l&#8217;Assurance chômage, en lieu et place des cotisations&nbsp;salariales. </p>
|
||
<p>https://www.unedic.org/a-propos/comprendre-le-financement-de-lassurance-chomage</p>
|
||
<h2 id="unedic"><span class="caps">UNEDIC</span></h2>
|
||
<p>L&#8217;<span class="caps">UNEDIC</span> est une association de délégation de service public, qui s&#8217;occupe de gérer l&#8217;assurance chômage, en coopération avec Pôle&nbsp;Emploi.</p>
|
||
<p>L&#8217;Assurance chômage est financée par les cotisations des employeurs et par une partie de la <span class="caps">CSG</span> pour les salariés. Une cotisation a toutefois été maintenue pour les intermittents du&nbsp;spectacle.</p>
|
||
<p>Elle vise à assurer un revenu de remplacement aux salariés involontairement privés d&#8217;emploi et à accélérer leur retour à l’emploi par le financement d’aides et de prestations&nbsp;adaptées. </p>
|
||
<p>Obligée, par ses statuts, d&#8217;équilibrer son budget, l&#8217;Unedic ne peut remplir sa mission, qui porte sur le paiement régulier des allocations de chômage, que si les dépenses sont globalement alignées sur les&nbsp;ressources.</p>
|
||
<p>De ce fait, en 2002, une partie des partenaires sociaux de l&#8217;Unedic (<span class="caps">MEDEF</span>, <span class="caps">CFDT</span>, <span class="caps">CFTC</span> et <span class="caps">CFE</span>-<span class="caps">CGC</span>) a accepté de signer une convention réduisant la durée d&#8217;indemnisation de la majorité des chômeurs. Ce choix a été fait dans le souci de préserver le <span class="caps">PARE</span>, et de ne pas toucher au principe de non-dégressivité dans le calcul des&nbsp;indemnités. </p>
|
||
<h2 id="plan-daide-au-retour-a-lemploi-pare">Plan d&#8217;aide au retour à l&#8217;emploi (<span class="caps">PARE</span>)</h2>
|
||
<p>Engagement signé entre le chômeur et le Pôle emploi de tout mettre en œuvre pour que celui-ci retrouve rapidement un emploi. Les Assedic ne se bornent plus à verser un revenu de remplacement au demandeur d&#8217;emploi; elles l&#8217;aident à revenir vers l&#8217;emploi dans le cadre d&#8217;un projet défini avec lui, de manière&nbsp;contractuelle.</p>
|
||
<p>En 2000, dans un contexte d&#8217;excédent budgétaire (1,3 milliard d&#8217;euros), les partenaires sociaux adoptent le <span class="caps">PARE</span>. Prévoyant un surplus financier de 18 milliards d&#8217;euros sur les trois années suivantes selon les modalités de la convention précédente, <strong>les partenaires décident de redistribuer cette somme au travers d&#8217;une baisse des cotisations patronales</strong> et d&#8217;un financement de certaines structures&nbsp;d&#8217;insertion. </p>
|
||
<p>Imposé par le <span class="caps">MEDEF</span>&nbsp;?</p>
|
||
<h2 id="reforme-chomage-de-2019">Reforme chômage de&nbsp;2019</h2>
|
||
<ul>
|
||
<li>Il faudra avoir travaillé 6 mois (contre 4 mois) sur les 24 derniers mois (contre 28 mois) pour percevoir une allocation de retour à l’emploi&nbsp;;</li>
|
||
<li>Le rechargement des droits à l’indemnisation chômage est repoussé à 6 mois (contre 1 mois avant la réforme)&nbsp;;</li>
|
||
</ul></content><category term="notes"></category></entry><entry><title>Prix libre et conscient & culpabilisation</title><link href="https://blog.notmyidea.org/prix-libre-et-conscient.html" rel="alternate"></link><published>2019-12-11T00:00:00+01:00</published><updated>2019-12-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-12-11:/prix-libre-et-conscient.html</id><summary type="html"><p>J&#8217;avais envie de réagir suite à la lecture d&#8217;une <a href="https://oncletom.io/2019/12/10/exemple-prix-libre-conscient/">note dans le journal de Thomas</a> qui parle de « prix libre <em>et</em> conscient&nbsp;».</p>
|
||
<p>Derrière le prix libre, je vois le fait que chacun⋅e paye ce qu&#8217;il ou elle veut, et ce qu&#8217;il ou elle peut. J …</p></summary><content type="html"><p>J&#8217;avais envie de réagir suite à la lecture d&#8217;une <a href="https://oncletom.io/2019/12/10/exemple-prix-libre-conscient/">note dans le journal de Thomas</a> qui parle de « prix libre <em>et</em> conscient&nbsp;».</p>
|
||
<p>Derrière le prix libre, je vois le fait que chacun⋅e paye ce qu&#8217;il ou elle veut, et ce qu&#8217;il ou elle peut. J&#8217;y vois également une sorte de solidarité entre les personnes qui peuvent donner plus et celles qui ne peuvent&nbsp;pas.</p>
|
||
<p>Pour une tenue d&#8217;évènement, voici les critères qui me paraissent intéressants&nbsp;:</p>
|
||
<ol>
|
||
<li>Chacun⋅e donne ce qu&#8217;iel&nbsp;peut;</li>
|
||
<li>Une <strong>solidarité entre les personnes qui le peuvent et celles qui le veulent</strong> est&nbsp;effective;</li>
|
||
<li>Les organisat⋅eurs⋅rices ne perdent pas&nbsp;d&#8217;argent;</li>
|
||
<li><strong>Les coûts sont assumés collectivement</strong> par l&#8217;ensemble des personnes, et non pas&nbsp;individuellement.</li>
|
||
<li>Les personnes qui donnent moins ne sont pas&nbsp;culpabilisées.</li>
|
||
</ol>
|
||
<p>Un des effets du prix libre est de permettre à des personnes qui ne pourraient pas s&#8217;offrir tel ou tel évènement de venir et de participer, <strong>sans les faire culpabiliser</strong> en fonction de la somme déposée dans la cagnotte, même si rien n&#8217;est&nbsp;donné.</p>
|
||
<p>Je trouve dommage qu&#8217;une solution qui déculpabilisait les pauvres (d&#8217;être pauvres…) évolue vers une solution où ceux-cis sont maintenant <em>conscients</em> du fait qu&#8217;ils ne peuvent plus participer, où alors que leur participation à un impact sur la tenue de&nbsp;l&#8217;évènement.</p>
|
||
<p>En d&#8217;autres termes, j&#8217;ai l&#8217;impression que la solution du « prix libre <em>et</em> conscient » vient contredire les points <code>1</code> et <code>5</code> de ma&nbsp;liste. </p>
|
||
<p>Je me questionne donc quand aux limites du prix libre : qu&#8217;est-ce qui pousse les organisateurices à choisir un « prix libre est conscient » plutôt qu&#8217;un simple « prix libre »&nbsp;?</p>
|
||
<p>De mon expérience, les participan⋅te⋅s donnent parfois pas assez. Quelques idées en vrac qui devraient permettre d&#8217;avoir un système de prix qui corresponde aux critères énoncés plus haut&nbsp;:</p>
|
||
<ul>
|
||
<li>Quand c&#8217;est possible, avoir une entrée libre avec une boîte à dons. Chacun⋅e y donne ce qu&#8217;il&nbsp;veut.</li>
|
||
<li>Avoir une jauge qui indique à quel point l&#8217;évènement est déficitaire ou excédentaire (particulièrement pour les évènements qui se déroulent sur plusieurs jours), et afficher cette jauge à la fin de&nbsp;l&#8217;évènement.</li>
|
||
</ul></content><category term="journal"></category></entry><entry><title>Écran et dépendances</title><link href="https://blog.notmyidea.org/ecran-et-dependances.html" rel="alternate"></link><published>2019-12-09T00:00:00+01:00</published><updated>2019-12-09T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-12-09:/ecran-et-dependances.html</id><summary type="html">
|
||
<p>Je réalise aujourd&#8217;hui à quel point ma vie est faite d&#8217;une multitude d&#8217;écrans, et à quel point le temps passe vite quand j&#8217;en <em>consomme</em> (j&#8217;utilise volontairement ce terme de <em>consommer</em>, tant j&#8217;ai le sentiment que c&#8217;est un bien de&nbsp;consommation).</p>
|
||
<p>Il y a …</p></summary><content type="html">
|
||
<p>Je réalise aujourd&#8217;hui à quel point ma vie est faite d&#8217;une multitude d&#8217;écrans, et à quel point le temps passe vite quand j&#8217;en <em>consomme</em> (j&#8217;utilise volontairement ce terme de <em>consommer</em>, tant j&#8217;ai le sentiment que c&#8217;est un bien de&nbsp;consommation).</p>
|
||
<p>Il y a quelques mois, j&#8217;ai choisi de ne pas avoir d&#8217;ordinateur à la maison durant une semaine. Résultat ? Je me suis remis à lire ! Depuis, j&#8217;essaye de reproduire quelque chose de similaire, mais me retrouve face à un triste constat : je suis&nbsp;drogué.</p>
|
||
<p>Les écrans sont trop présents. Comment faire sans eux ? Comment limiter leur pouvoir sur mon temps ? Que de questions&nbsp;:-)</p></content><category term="journal"></category></entry><entry><title>Groupe de paroles hommes</title><link href="https://blog.notmyidea.org/groupe-de-paroles-hommes.html" rel="alternate"></link><published>2019-11-23T00:00:00+01:00</published><updated>2019-11-23T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-11-23:/groupe-de-paroles-hommes.html</id><summary type="html">
|
||
<p><em>Questionner la non-mixité&nbsp;hommes</em></p>
|
||
<p>Il y a maintenant peut-être six mois, à l&#8217;appel d&#8217;un ami, je me suis mis à participer à un « groupe de parole » d&#8217;hommes. L&#8217;idée m&#8217;est d&#8217;abord apparue comme intéressante pour pouvoir discuter de certaines problématiques <em>entre hommes</em> , entre autres des …</p></summary><content type="html">
|
||
<p><em>Questionner la non-mixité&nbsp;hommes</em></p>
|
||
<p>Il y a maintenant peut-être six mois, à l&#8217;appel d&#8217;un ami, je me suis mis à participer à un « groupe de parole » d&#8217;hommes. L&#8217;idée m&#8217;est d&#8217;abord apparue comme intéressante pour pouvoir discuter de certaines problématiques <em>entre hommes</em> , entre autres des questions de rapport à l&#8217;autre dans les relations&nbsp;intimes.</p>
|
||
<p>J’appréciais alors l&#8217;idée de chercher à déconstruire les dominations masculines, et en parler entre hommes me paraissait un bon moyen de venir questionner certains comportements (oppressifs), sans avoir des personnes opprimées en face pour juger des situations. Quelque part, l&#8217;envie était donc de se questionner collectivement sur ce qu&#8217;on (les hommes) fait vivre comme société, en tant que&nbsp;groupe.</p>
|
||
<p>Je cherchais à pouvoir discuter, dans un « cercle bienveillant », de mes questionnements par rapport aux relations intimes, mais aussi d&#8217;une manière générale par rapport à notre société. À avoir des regards extérieurs sur mes ressentis, à venir questionner certains de mes comportements, à trouver des interactions intimes, et peut-être de manière inconsciente à me réconforter sur une posture que j&#8217;adopte en tant&nbsp;qu&#8217;homme.</p>
|
||
<p>La raison pour laquelle être « entre hommes » m&#8217;a paru intéressante de prime abord est de pouvoir discuter de notre « masculinité » de manière sensible, de venir questionner notre relation aux autres et de le faire sans être jugés par des personnes opprimées par mon comportement (que celui ci soit conscient ou non). Un moyen de libérer notre parole sur des sujets pas évidents, en quelques&nbsp;sorte.</p>
|
||
<h2 id="et-puis">Et&nbsp;puis…</h2>
|
||
<p>Au fil des rencontres, les sujets abordés ont été vastes : on a parlé de violence <span class="caps">VS</span> non-violence, de rapport à nos mères, de rapport à nos dépendances, de métaphysique, de sexisme. Pour moi le moment ou on à commencé à parler de sexisme marque un tournant dans l&#8217;histoire du&nbsp;groupe.</p>
|
||
<p>On s&#8217;est alors trouvés dans une situation où des désaccords se sont manifestés. Désaccords liés à la reconnaissance de nos privilèges en tant qu&#8217;hommes. Refaire le débat ne me semble pas vraiment instructif, mais j&#8217;ose croire que les discussions qui ont eu lieu ont permis à chacun de nous d&#8217;évoluer dans notre auto-critique personnelle. Je crois que ces discussions étaient&nbsp;utiles.</p>
|
||
<p>Ces discussions ont également éveillé en moi l&#8217;envie de questionner la non-mixité de notre groupe. Pour quelle raison(s) se réunir en non-mixité ? Pourquoi exclure les femmes de nos rendez-vous&nbsp;?</p>
|
||
<p>Notez bien que je ne questionne pas ici la question de la non-mixité dans un groupe d&#8217;opprimé⋅e⋅s, mais bel et bien dans un groupe&nbsp;d&#8217;oppresseurs.</p>
|
||
<p>Ne pas être confronté au regard des femmes nous permet de ne pas nous sentir coupables face à certains de nos comportements — sexistes . Cela nous permet donc d&#8217;accepter d&#8217;en parler, de rompre le tabou, alors même qu&#8217;on les estime, quelque part, <em>déviants</em>.</p>
|
||
<p>On cherche à créer une sorte de cocon (douillet et chaud) pour pouvoir exprimer nos doutes sur nos comportements, sans être remis en cause, et surtout sans être&nbsp;jugés.</p>
|
||
<p>Potentiellement, le fait de se retrouver entre hommes, sans l&#8217;avis de <em>l&#8217;autre sexe</em> signifie aussi qu&#8217;on peut se rassurer sur la déviance de ces comportements, pour — de manière consciente ou non — se sentir mieux, et donc asseoir notre domination&nbsp;masculine.</p>
|
||
<h2 id="questionner-la-non-mixite">Questionner la&nbsp;non-mixité</h2>
|
||
<p>J&#8217;en viens donc a questionner le choix de la non-mixité pour ce groupe de parole, de manière personnelle d&#8217;abord, puis ensuite de manière ouverte, au reste du&nbsp;groupe.</p>
|
||
<p>Ce qu&#8217;on fait lors de notre groupe de parole me semble nouveau : se parler entre personnes d&#8217;horizons différents, déconstruire nos comportements, se donner des astuces sur comment déjouer tel ou tel mécanisme chez nous me semble louable, voire même&nbsp;nécessaire.</p>
|
||
<p>J&#8217;ai découvert avec ce groupe de parole un outil qui me semble&nbsp;utile.</p>
|
||
<p>Mais quand je challenge l&#8217;idée de la non-mixité, je ne trouve pas de raison — autre que la peur d&#8217;être jugé — de refuser la mixité dans notre groupe. Je crois qu&#8217;ouvrir nos discussions nous permettrait d&#8217;affronter certains sujets de manière plus&nbsp;juste.</p>
|
||
<p>Lors d&#8217;un de nos regroupements, nous décidons donc, après quelques discussions, d&#8217;ouvrir le groupe à d&#8217;autres personnes, peu importe leur sexe, tout en cherchant à conserver un groupe de petite taille, pour que la création d&#8217;une confiance mutuelle soit plus simple à&nbsp;obtenir.</p></content><category term="journal"></category></entry><entry><title>Ignorance et vertu</title><link href="https://blog.notmyidea.org/ignorance-et-vertu.html" rel="alternate"></link><published>2019-11-23T00:00:00+01:00</published><updated>2019-11-23T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-11-23:/ignorance-et-vertu.html</id><summary type="html">
|
||
<blockquote>
|
||
<p>Rester dans une position de <em>sachant</em> semble me pousser à des comportements de fermeture&nbsp;d&#8217;esprit.</p>
|
||
</blockquote>
|
||
<p>Reconnaître mon ignorance me permet de découvrir de laisser mes interlocut⋅eurs⋅rices m&#8217;expliquer de manière claire ce que je ne connais pas encore, là où laisser penser que je connais ne m …</p></summary><content type="html">
|
||
<blockquote>
|
||
<p>Rester dans une position de <em>sachant</em> semble me pousser à des comportements de fermeture&nbsp;d&#8217;esprit.</p>
|
||
</blockquote>
|
||
<p>Reconnaître mon ignorance me permet de découvrir de laisser mes interlocut⋅eurs⋅rices m&#8217;expliquer de manière claire ce que je ne connais pas encore, là où laisser penser que je connais ne m&#8217;apporte que du flou et une posture éthiquement&nbsp;bancale.</p></content><category term="journal"></category></entry><entry><title>Fatigue et compétition</title><link href="https://blog.notmyidea.org/fatigue-et-competition.html" rel="alternate"></link><published>2019-11-17T00:00:00+01:00</published><updated>2019-11-17T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-11-17:/fatigue-et-competition.html</id><summary type="html">
|
||
<p>Je me rends compte que la compétition est présente, dans plusieurs sphères de ma vie, et qu&#8217;il s&#8217;agit d&#8217;une des choses qui me fait me sentir parfois en déséquilibre, voire qui me fait réagir d&#8217;une manière qui me semble&nbsp;étrangère.</p>
|
||
<p>Quand je rencontre ce mode de …</p></summary><content type="html">
|
||
<p>Je me rends compte que la compétition est présente, dans plusieurs sphères de ma vie, et qu&#8217;il s&#8217;agit d&#8217;une des choses qui me fait me sentir parfois en déséquilibre, voire qui me fait réagir d&#8217;une manière qui me semble&nbsp;étrangère.</p>
|
||
<p>Quand je rencontre ce mode de fonctionnement chez d&#8217;autres, il arrive qu&#8217;il suscite un retour de ma part, comme si je ne savais pas encore désamorcer ce fonctionnement en moi, et je rentre alors dans le « jeu&nbsp;».</p>
|
||
<p>J&#8217;ai quand même réussi à plusieurs reprises à le détecter, mais parfois un côté un peu « automatique » ressort, presque animal, et je rentre alors dans ce mode de discussion qui m&#8217;est proposé, sans même m&#8217;en rendre&nbsp;compte.</p>
|
||
<p>Je n&#8217;y trouve pas grand intérêt, et je développe une forte envie de venir à bout de ces mécanismes ancrés en&nbsp;moi.</p>
|
||
<p>Lorsque je décèle que je rentre en compétition, je cherche à changer ma posture : je demande des précisions à mon interlocut⋅eur⋅rice plutôt que d&#8217;y opposer une connaissance que je pense détenir (voire même que je créé parfois sur le moment&nbsp;?).</p>
|
||
<p>Ça me renvoie au fait qu&#8217;il me semble mieux de ne pas savoir, plutôt que d&#8217;affirmer quelque chose dont je ne suis pas pas certain (même avec&nbsp;aplomb).</p></content><category term="journal"></category></entry><entry><title>Francis Dupuis Déri, Démocratie.</title><link href="https://blog.notmyidea.org/francis-dupuis-deri-democratie.html" rel="alternate"></link><published>2019-11-15T00:00:00+01:00</published><updated>2019-11-15T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-11-15:/francis-dupuis-deri-democratie.html</id><summary type="html">
|
||
<p><em>Ces notes sont extraites de deux ressources : une discussion autour de la notion de « Démocratie », organisé par la Fédération Anarchiste de Rennes, avec comme invité Françis Dupuis-Déri, et <a href="https://www.thinkerview.com/francis-dupuis-deri-democratie-marketing-politique-pour-les-pauvre">une vidéo sur Thinkerview</a>.</em></p>
|
||
<p>Le discours dominant indique que, à Athènes, les fonctions sont tirées au sort. Les fonctions ont peu de …</p></summary><content type="html">
|
||
<p><em>Ces notes sont extraites de deux ressources : une discussion autour de la notion de « Démocratie », organisé par la Fédération Anarchiste de Rennes, avec comme invité Françis Dupuis-Déri, et <a href="https://www.thinkerview.com/francis-dupuis-deri-democratie-marketing-politique-pour-les-pauvre">une vidéo sur Thinkerview</a>.</em></p>
|
||
<p>Le discours dominant indique que, à Athènes, les fonctions sont tirées au sort. Les fonctions ont peu de pouvoir. Principe de rotation des taches. Pour éviter de développer des&nbsp;privilèges. </p>
|
||
<p>Il y a quelques situation de pouvoir avec les jurys (501 citoyens qui forment un jury), il n&#8217;y a pas de juge, pas d&#8217;avocat Les parties s&#8217;auto-représentent, le jury prends la&nbsp;décision.</p>
|
||
<p>Puis par la suite en 1770, la démocratie à été refondée pour créer la — soit disant — démocratie moderne . Dans la civilisation moderne, la démocratie n&#8217;est plus dans une citée, il faut donc faire en fonction de la nation. Les gens sont trop nombreux pour s&#8217;assembler, et donc il faut la démocratie représentative. « C&#8217;est la même chose, mais différent&nbsp;». </p>
|
||
<h2 id="ce-recit-est-en-fait-fallacieux">Ce récit est en fait&nbsp;fallacieux.</h2>
|
||
<p>Il n&#8217;y a pas de lien entre Athènes et le parlement qu&#8217;on a maintenant (ou le congrès,&nbsp;etc).</p>
|
||
<p>Les parlements sont une création du moyen age, vers le 12eme ou 13eme siècle (voire certaine formes de proto-parlement vers le 9eme&nbsp;siècle).</p>
|
||
<p>Ce sont des moments ou le roi convoque les grands du royaume (de manière un peu arbitraire), et à ce moment il n&#8217;y a pas encore de parlement en tant que tel (bâtiment). Les lieux changent, ça peut être dans un monastère, dans un château,&nbsp;etc.</p>
|
||
<p>Les grands du royaumes ont prêtés serment de protéger le roi, <span class="caps">ET</span> de le&nbsp;conseiller.</p>
|
||
<p>Le roi à besoin d&#8217;aide pour prélever les taxes. Au moyen age, les rois ne connaissent pas leur population (pas de recensement, par ex. il y a des débats à l&#8217;époque sur le nombre de personnes dans une&nbsp;ville)</p>
|
||
<p>L&#8217;origine du parlementarisme est en fait ces premières rencontres. Au fil des générations et des siècles, et des crises militaires etc. ces rencontres vont donner des occasions aux grands du royaume de négocier. Des crises éclatent par ex dans ce genre de rencontres (par ex. les états&nbsp;généraux).</p>
|
||
<p>Grosso-modo, les rôles des citoyens sont les mêmes, et l&#8217;executif et les parlementaires détiennent le pouvoir d&#8217;une manière&nbsp;générale.</p>
|
||
<p>Il faudrait en fait nommer ces systèmes « aristocraties électives ». C&#8217;est différent d&#8217;une aristocratie héréditaire, mais dans les deux cas il s&#8217;agit d&#8217;une logique&nbsp;aristocratique. </p>
|
||
<p>C&#8217;est donc un tout petit groupe, qui :
|
||
- A la prétention d&#8217;être « les meilleurs » (en fonction de différents critères : remporter les élections, avoir le « sang bleu », etc).
|
||
- Représente les classes supérieures, très largement privilégiées. Impossible par exemple d&#8217;avoir des chômeurs au sein de ce groupe (puisqu&#8217;on est député contre un salaire); Il y a des chefs d&#8217;entreprises, des les classes sup, des hommes majoritairement, des blancs, donc une disproportion des classes&nbsp;privilégiées.</p>
|
||
<h2 id="origines-histoire-du-mot-democratie">Origines / histoire du mot&nbsp;démocratie</h2>
|
||
<p><em>Dupuis-Déri indique s&#8217;appuyer sur les travaux de Pierre Rozon Valon, qui a travaillé sur le mot en&nbsp;France.</em></p>
|
||
<p>Lors des moments de rupture, on constate que les élites sont des parlementaires au sens large (par ex. Danton, Mauras, Robespierre, St just etc). Quand ils déclenchent leur rébellion (contre la couronne ou contre le parlement britannique par exemple), ils n&#8217;utilisaient pas le mot de&nbsp;démocratie.</p>
|
||
<p>Démocrate à ce moment la faisait référence à Athènes, au pouvoir de la plèbe, considéré comme dangereux, sanguinaire et immoral. Il s&#8217;agit du « pouvoir des pauvres ». Ils avaient appris à se méfier d&#8217;Athènes. Le modèle dominant à l&#8217;époque était . Leur modèle était à l&#8217;époque&nbsp;Rome.</p>
|
||
<p>2 générations plus tard (vers 1830 aux <span class="caps">US</span>, 1848 pour la France), le premier candidat à la présidence fait appel à ce concept de démocratie. Tout le monde se prétends alors démocrate, à des fins électorales. <a href="https://fr.wikipedia.org/wiki/Auguste_Blanqui">Auguste Blanqui</a> (révolutionnaire républicain socialiste français) dit alors&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Tout le monde si dit démocrate, on a mème des monarchistes démocrates. Le mot démocratie est devenu&nbsp;caoutchouc.</p>
|
||
</blockquote>
|
||
<p>En 1828 aux <span class="caps">USA</span> il y a des campagnes électorales, les présidents se présentent comme des républicains. Andrew Jackson perd les élections, et pour pouvoir gagner, ils se représente à d&#8217;autres élections comme démocrate. En étant contre l&#8217;aristocratie financière, et en s&#8217;adressant directement au peuple, le peuple va penser que tu prends sa défense. Par la suite tous les candidats se sont dits&nbsp;démocrates. </p>
|
||
<p>Dans le cas de la France, sous la monarchie restaurée, l&#8217;utilisation du mot « république » est considéré dangereux et condamné. En cherchant un mot de remplacement ils se disent&nbsp;démocrates.</p>
|
||
<p>Cette stratégie de rhétorique, de propagande, crée de la confusion. Le peuple à donc été privé de ce mot de démocratie (vidé de son&nbsp;sens).</p>
|
||
<p>On pense que la nation s&#8217;incarne dans l&#8217;assemblée nationale, par une sorte de pensée magique, de chamanisme. On peut voir les élections comme un rituel qui permet de fusionner ses voix avec les autres voix de la nation,&nbsp;etc.</p>
|
||
<h2 id="des-exemples-dauto-gestion">Des exemples&nbsp;d&#8217;auto-gestion</h2>
|
||
<p>Malgré tout ça, l&#8217;élite politique n’arrive pas à empêcher des expressions de vraies démocraties aujourd&#8217;hui. L&#8217;humanité à expérimenté plein de situations, ou elles pratiquent ce qu&#8217;on devrait appeler la démocratie&nbsp;:</p>
|
||
<p>Dans les communautés Mohawks (autochtones d&#8217;Amérique du nord) ou chez <a href="https://fr.wikipedia.org/wiki/Inuits">inuits</a>, ils y en avait plusieurs qui vivaient de manière non-hiérarchique, il n&#8217;y avait pas de propriété privée. Les chefs autochtones n&#8217;ont pas de pouvoir coercitif, pas de juge, pas de prison, pas de police, la seule chose que les chefs ont est un prestige lié à par ex leurs capacités de chasseurs. Mais ils n&#8217;ont pas de pouvoir réel. C&#8217;est pour cette raison que les autochtones étaient pris pour des peuples « pas fiables », le chef est un simple porte parole, mais ce n&#8217;est pas lui qui prends les&nbsp;décisions.</p>
|
||
<p>D&#8217;autres par ex les capviles&nbsp;(?)</p>
|
||
<p>Au moyen age il y avait des assemblées d&#8217;habitants. Ça ressemblait presque à de l&#8217;autogestion. Des communautés paysannes. Il y avait alors des communs (moulin, séchoir, puis, église) qui était gérés par la communauté d&#8217;habitants. Gérés par des assemblées d&#8217;habitants (10, 12, 14 assemblées par an), pour décider des choses à&nbsp;faire.</p>
|
||
<p>Les guildes sont très importantes à l&#8217;époque, les guildes décident en assemblée de comment on travaille, selon quels critères, formation, promotion, ils peuvent avoir des milices et participer à la défense de leurs villes, et se poursuivre les uns les autres, sans aucune intervention du pouvoir central. C&#8217;est donc un mode de vie qui ne fonctionne pas selon les « règles du régime&nbsp;».</p>
|
||
<h2 id="tradition-anti-parlementariste">Tradition anti&nbsp;parlementariste</h2>
|
||
<p>Plutôt que de penser que c&#8217;est totalisant — il y a des ministères pour tout, une prétention de l&#8217;état à tout gérer —, il y a encore la possibilité de vivre quelque chose qui ressemble à la démocratie : dans nos quartiers, sur le <span class="caps">ZAD</span>,&nbsp;etc.</p>
|
||
<p>Il y a une tradition anti-parlementariste, qui dit que le peuple à la capacité à s&#8217;autogérer, et que les décisions ne doivent pas êtres gérées par le&nbsp;parlement.</p>
|
||
<p>Dans les grandes crises, c&#8217;est ce que le peuple fait (en argentine au début des années 2000, durant le printemps arabe, dans les crises sociales et politiques). Les gens s&#8217;assemblent, et ensuite décident ensemble d&#8217;éviter de nommer de nouveaux chefs. Cet esprit anti-parlementariste continue d&#8217;exister, et continue à faire peur. La peur est celle de&nbsp;l&#8217;émeute.</p>
|
||
<p>il y a d&#8217;ailleurs plein de lois contre les attroupements illégaux. C&#8217;était déjà le cas à l&#8217;époque des esclaves : interdiction des regroupement. En 1789, les parlementaires ont décidé d&#8217;interdire aux femmes de se&nbsp;rassembler.</p>
|
||
<p>Également, il y a eu énormément d&#8217;émeutes aux <span class="caps">US</span> à l&#8217;époque de Martin Luther King, et même <span class="caps">MLK</span> (qui était plutôt contre) disait alors qu&#8217;il y avait un sens derrière ces émeutes, et qu&#8217;il fallait condamner aussi ce qui à amené à cette&nbsp;situation. </p>
|
||
<p>—&nbsp;20h19</p>
|
||
<h1 id="questions-discussion">Questions /&nbsp;Discussion</h1>
|
||
<p>Il y a eu pas mal de questions / réponses et discussions. Je n&#8217;ai pris des notes que sur une partie d&#8217;entre&nbsp;elles.</p>
|
||
<h3 id="on-est-contre-lassembleisme-quest-ce-que-ca-veut-dire">On est contre l&#8217;assembléisme » ? Qu&#8217;est-ce que ça veut dire&nbsp;?</h3>
|
||
<p>Il y a toujours ce débat: élection/pas élection. Il y a toujours des personnes qui veulent écrire une nouvelle constitution, un comité sur le sexisme, etc. Ce sont des choses qui se retrouvent dans la plupart des&nbsp;mouvements.</p>
|
||
<h3 id="inclusion-et-extinction-rebellion">Inclusion et extinction&nbsp;rébellion</h3>
|
||
<p>Je n&#8217;ai pas noté la question, mais elle traitait sur le fait que xR se disait inclusif et qu&#8217;en fait iels ne l&#8217;étaient sûrement pas&nbsp;réellement.</p>
|
||
<p>Il y a toujours — dans les groupes que je pratique — des principes, mais c&#8217;est pas ça qui fait que les gens se regroupent. Les mouvements sociaux existent déjà, ce sont des groupes qui existent déjà. Quand vous avez un groupe de 10-15 personnes avec des profils similaires aux vôtres, ça va pas faire venir d&#8217;autres&nbsp;personnes.</p>
|
||
<p>xR c&#8217;est un collectif militant de personnes qui se connaissent au début. Un appel avec un format, un langage, qui parle à une certaine partie de la&nbsp;population.</p>
|
||
<p>Un autre intervenant indique que « les groupes sont ce qu&#8217;ils sont. Qu&#8217;ils existent, qu&#8217;ils agissent, ça me dérange pas. Quand ça me dérange, c&#8217;est quand ils prétendent représenter d&#8217;autres personnes que ce qu&#8217;ils sont.&nbsp;»</p>
|
||
<h3 id="exemple-sde-systemes-democratiques">Exemple sde systèmes&nbsp;démocratiques</h3>
|
||
<p>Est-ce que vous avez connaissance d&#8217;un pays qui à un système démocratique « normal »&nbsp;?</p>
|
||
<p>La démocratie, avec 65M de personnes c&#8217;est pas vraiment faisable. Ça n’empêche pas d&#8217;avoir des instances de fédération. Exercheia à Athènes, au Rojava mais ce sont des endroits ou la liberté est&nbsp;précaire.</p>
|
||
<h3 id="que-penser-du-ric">Que penser du <span class="caps">RIC</span>&nbsp;?</h3>
|
||
<p>Ma compréhension c&#8217;est qu&#8217;en Suisse ou en Californie (où c&#8217;est possible), ces référendums, dans le cadre de nations, quand ils sont actés dans des sociétés inégalitaires — en terme de moyens financiers, de prise de parole dans les médias etc — donnent l&#8217;illusion que le camp du oui et du non sont à forces égales, alors qu&#8217;en fait ce sont des campagnes électorales très inégalitaires. Ce qui favorise certaines parce que les moyens ne sont pas&nbsp;égaux.</p>
|
||
<p>De plus, les résultats sont reçus et gérés par les élus. Ma compréhension c&#8217;est que certaines décisions populaires ne sont pas&nbsp;adoptées.</p>
|
||
<h3 id="avancees-sociales-et-democratie-directe">Avancées sociales et démocratie&nbsp;directe</h3>
|
||
<p>Si on avait une démocratie directe, aurait-on eu les avancées sociales actuelles&nbsp;?</p>
|
||
<p>Autrement dit, si on donnait le pouvoir au peuple, qu&#8217;est-ce que ça donnerait (dans les pays occidentaux)&nbsp;?</p>
|
||
<p>On peut remettre en question le fait qu&#8217;il y ait vraiment des avancées <em>partout</em>. Par exemple, pour l&#8217;avortement, c&#8217;est l&#8217;état qui l&#8217;a interdit, au moyen age en premier lieu. Les femmes connaissaient les moyens de se faire avorter, alors qu&#8217;aujourd&#8217;hui les femmes ont très peu de compétences pour pouvoir pratiquer l&#8217;avortement elles&nbsp;mêmes.</p>
|
||
<p>C&#8217;est difficile d&#8217;imaginer. Il y aurait une diversité de systèmes juridiques. La république est en fait plus réactionnaire que la monarchie qui la précède (entre autre sur le sexisme, le racisme). Ce sont les mobilisations qui font évoluer les situations, ce n&#8217;est pas vraiment l&#8217;état qui fait progresser. L&#8217;état n&#8217;est pas progressiste (ou conservateur d&#8217;ailleurs) par définition, il ne fait qu&#8217;appliquer le&nbsp;status-quo.</p>
|
||
<h3 id="avoir-de-meilleures-assemblees-representatives">Avoir de meilleures assemblées représentatives&nbsp;?</h3>
|
||
<p>A : Est-ce que chercher à constituer des assemblées plus représentatives, « meilleures », voir qui représentent plus les dominés peut être bénéfique&nbsp;?</p>
|
||
<p>B : Qu&#8217;est-ce qui nous dit qu&#8217;avec ces assemblées on va pas se retrouver dans la même situation qu&#8217;actuellement ? Ça reste de base des gens qui prennent des décisions pour d&#8217;autres. Le principe est fondamentalement glissant. risque de défendre ses propres intérêts plutôt que le reste de la&nbsp;population.</p>
|
||
<p>A : Il y a la potentialité de ne pas opposer les deux modèles ? Ce sont des tentatives de bricolages, pour avoir plus de démocratie et de justice sociale dans le&nbsp;système.</p>
|
||
<p>C (Isabelle Attard ?): Le pouvoir corrompt. On pense pouvoir lui mettre des gardes fous, pour pouvoir faire le mieux. Mon expérience c&#8217;est qu&#8217;au bout de 6 mois, le système intègre, absorbe, il est prévu pour ça. Imaginer que nous pourrions créer cette assemblée idéale, ne marche pas. Comme beaucoup d&#8217;autres personnes, j&#8217;y ai&nbsp;cru.</p>
|
||
<h3 id="ressources">Ressources</h3>
|
||
<p>Quelques ressources citées par des personnes présentes ou par&nbsp;Dupuis-Déri</p>
|
||
<ul>
|
||
<li>« De la horde à l&#8217;état », qui explique que seuls des petits groupes de petite taille peuvent&nbsp;fonctionner.</li>
|
||
</ul>
|
||
<h1 id="autres-notes-prises-durant-via-la-video">Autres notes prises durant via la&nbsp;vidéo</h1>
|
||
<p><em>Les notes de cette partie sont plus en vrac&nbsp;;-)</em></p>
|
||
<h2 id="pouvoir-et-systeme-electoral">Pouvoir et système&nbsp;électoral</h2>
|
||
<p>Quand on créé un groupe anarchiste, il y a des pouvoirs informels et tout le monde n&#8217;est pas égal dans la réalité, mais ces groupes mettent en place des manières de réduire ces inégalités, ces jeux d&#8217;influence. Il rexiste des techniques pour réduire le pouvoir&nbsp;informel.</p>
|
||
<p>A chaque fois qu&#8217;il y a des gens aux pouvoir, il y a une forme de démagogie. La démagogie fait croire qu peuple qu&#8217;on est là pour son bien, alors que l&#8217;objectif est d&#8217;asseoir le pouvoir. La démagogie est inscrite dans l&#8217;<span class="caps">ADN</span> du système électoral. Vous voulez vous faire élire. Et donc vous souhaitez que les gens votent pour vous. Ce système électoral encourage le&nbsp;mensonge.</p>
|
||
<h2 id="repression">Répression</h2>
|
||
<p>L&#8217;état Français, Canadien, Americain, Britanique etc ont déjà tout un arsenal pour punir les casseurs (terme foncièrement péjoratif). Ils en re-créent pour consolider, densifier leur arsenal, et c&#8217;est également une opération politique. Ça donne quelques nouveaux outils à la police, mais la police à énormément de moyens déjà actuellement. Il s&#8217;agit principalement d&#8217;un moyen de montrer qu&#8217;il se passe quelque&nbsp;chose.</p>
|
||
<h2 id="vote-decisions-collectives">Vote / Décisions&nbsp;collectives</h2>
|
||
<p>Un endroit ou on aurait vraiment la place et le temps, ce sont les écoles […]. Mais ils nous font élire des conseils d&#8217;élèves. On nous apprends à élire des personnes. L&#8217;agence para-gouvernementale explique que c&#8217;est pour former les enfants à voter. Quand on est adultes, on mets en scène l&#8217;acte exactement dans le même lieu (les&nbsp;écoles).</p>
|
||
<p>Ce qui vient avec c&#8217;est que le pouvoir politique passe par le vote. C&#8217;est plus important de faire voter, que de faire élire. On essaye de convaincre les enfants que l&#8217;action politique est canalisée par le&nbsp;vote.</p>
|
||
<p>Les gens qui déclarent la guerre ne la font pas (ni leurs enfants&nbsp;d&#8217;ailleurs)</p>
|
||
<p>L&#8217;idée n&#8217;est pas de créer un n-ième parti d&#8217;opposition. J&#8217;ai beaucoup d&#8217;espoir dans les mouvement sociaux autonomes. C&#8217;est là ou il y a des choses intéressantes au niveau politique. C&#8217;est en échangeant, en discutant qu&#8217;on pratique de la&nbsp;politique.</p>
|
||
<p>Vous pensez que la liberté, c&#8217;est le temps libre. On va penser que les assemblées sont un « perte de temps ». C&#8217;est dommage parce que c&#8217;est le seul moment ou on peut être libre politiquement. Alors qu&#8217;on pense qu&#8217;on perds du temps. Les assemblées sont là ou on peut vivre la politique concrètement. Nos activité politiques vont nous sembler inutiles parce que dans nos vies on ne contrôle pas grand chose. Les discussions sont intéressantes quand les enjeux sont au&nbsp;rendez-vous.</p>
|
||
<p>Si on avait plus de communs à gérer entre nous, là on trouverait un temps et peut être même un plaisir à s&#8217;investir dans ces thèmes. Puisque rien ne nous appartiens, alors à quoi bon parler avec ses voisins ? On parlerait de quoi&nbsp;?</p>
|
||
<h2 id="basculement">Basculement</h2>
|
||
<p>Je ne sais pas la solution. J&#8217;ai des idées. Les vraies grandes transformations dans les sociétés se sont rarement passées parce que quelqu&#8217;un avec des amis à établi un plan de match. C&#8217;est pas comme ça que ça se passe. Le régime est déstabilisé à un moment donné, il y a une crise dans l&#8217;élite. Il faut que l&#8217;élite soit déstabilisée. Quand l&#8217;élite se tiens les coudes, les forces militaires tiennent, etc. Vous risquez simplement de vous faire&nbsp;écraser.</p>
|
||
<h2 id="crise-de-la-masculinite">Crise de la&nbsp;masculinité</h2>
|
||
<p>Il y a ce discours de la crise de la masculinité. Il s&#8217;agit d&#8217;un discours, de rhétorique. A travers des études historiques, j&#8217;ai constaté qu&#8217;en occident depuis 500 ans, des hommes disent qu&#8217;il y a une crise de la masculinité […] en France, en Allemagne et ailleurs […]. Ce discours est tellement permanent, tellement universel, et donc il ne peut pas être autre chose que de la propagande, une sorte d&#8217;appel à l&#8217;aide envers les autres hommes, pour pouvoir&nbsp;contre-attaquer.</p>
|
||
<h2 id="violence-non-violence">Violence / Non&nbsp;violence</h2>
|
||
<p>Les mouvement sociaux sont en permanence traversés par le débat violence / non violence. Aux états-unis, en Italie et ailleurs, des conflits éclatent, par exemple parce que certain⋅e⋅s militant⋅e⋅s voulaient amener des pinces, pour faire un trou dans un&nbsp;grillage.</p>
|
||
<p>On parle donc d&#8217;une pince à ciseler un clôture d&#8217;un réacteur nucléaire. Il ne faut surtout pas casser les vitrines de banques parce que c&#8217;est de la violence. C&#8217;est incroyable. Dans les mouvement sociaux, des personnes sont tellement concernés par la violence que ça crée des débats. Le débat éthique violence / non-violence est traversé par des exemples qui sont mal compris. Par exemple Gandi et <span class="caps">MLK</span>.</p>
|
||
<p>Mais c&#8217;est une illusion complète. Dans le mouvement d&#8217;indépendance de l&#8217;inde auquel participait gandi, dans le même mouvement des personnes attaquaient avec des bombes et des&nbsp;mitraillettes.</p></content><category term="notes"></category></entry><entry><title>Musique, création et partage</title><link href="https://blog.notmyidea.org/musique-creation-et-partage.html" rel="alternate"></link><published>2019-11-14T00:00:00+01:00</published><updated>2019-11-14T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-11-14:/musique-creation-et-partage.html</id><summary type="html">
|
||
<p>J&#8217;arrive à trouver du temps libre pour faire de la musique. Après quasiment deux ans à jouer seul, je me remets à faire de la musique avec un ami, et j&#8217;y (re)trouve un grand&nbsp;plaisir.</p>
|
||
<p>Composer, proposer, écouter, échanger, faire évoluer des sons et des idées se …</p></summary><content type="html">
|
||
<p>J&#8217;arrive à trouver du temps libre pour faire de la musique. Après quasiment deux ans à jouer seul, je me remets à faire de la musique avec un ami, et j&#8217;y (re)trouve un grand&nbsp;plaisir.</p>
|
||
<p>Composer, proposer, écouter, échanger, faire évoluer des sons et des idées se passe sans encombre, retrouver cette passion que j&#8217;avais mise de côté me&nbsp;plaît.</p>
|
||
<p>Je sors de ma zone de confort : je joue sur un synthé analogique et j&#8217;apprends à faire un peu d&#8217;enregistrement sonore par la même&nbsp;occasion.</p></content><category term="journal"></category></entry><entry><title>Élitisme et apprentissage</title><link href="https://blog.notmyidea.org/elitisme-et-apprentissage.html" rel="alternate"></link><published>2019-11-01T00:00:00+01:00</published><updated>2019-11-01T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-11-01:/elitisme-et-apprentissage.html</id><summary type="html">
|
||
<p>Au fur et à mesure de mes apprentissages, il y a quelque chose que j&#8217;ai du mal à déconstruire: le mythe du meilleur. Moi qui pense qu&#8217;ensemble on va plus loin, et que la compétition n&#8217;a pas de bons jours devant elle, je me retrouve parfois dans …</p></summary><content type="html">
|
||
<p>Au fur et à mesure de mes apprentissages, il y a quelque chose que j&#8217;ai du mal à déconstruire: le mythe du meilleur. Moi qui pense qu&#8217;ensemble on va plus loin, et que la compétition n&#8217;a pas de bons jours devant elle, je me retrouve parfois dans des situations où j&#8217;ai une <em>envie</em> de montrer que je suis meilleur, que je sais mieux que mon voisin. Notamment lors de l&#8217;apprentissage via mes&nbsp;pairs.</p>
|
||
<p>Dans les domaines dans lesquels je me spécialise (fabrication de bière, informatique et programmation) je me rends compte qu&#8217;une certaine forme d’élitisme existe parfois, contrairement aux apparences de surface. Avoir une position de <em>sage</em> flatte mon&nbsp;égo.</p>
|
||
<h2 id="bonnes-pratiques-et-elitisme">Bonnes pratiques et&nbsp;élitisme</h2>
|
||
<p>Il ne faut sûrement pas confondre les bonnes pratiques avec l&#8217;élitisme, mais parfois la frontière se fait ténue. En guise d&#8217;exemple, dans le domaine du brassage, on va critiquer les personnes qui ne contrôlent pas la température de leurs fermentations alors qu&#8217;il s&#8217;agit probablement de leur apprentissage personnel. Contrôler cette température est une bonne pratique, qui constitue deux groupes: ceux qui savent et ceux qui ne savent&nbsp;pas.</p>
|
||
<p>Ceux qui savent vont alors <em>expliquer</em> à ceux qui apprennent, et ceux qui apprennent vont être contents d&#8217;apprendre. Il est à mon avis important de garder une posture d&#8217;apprenant alors même qu&#8217;on a des choses à transmettre. Que faut-il alors faire ? Dois-je garder du recul sur mes avis, ou dois-je les formuler comme étant des avis personnels, a prendre avec des pincettes&nbsp;?</p>
|
||
<h2 id="connaitre-mes-limites">Connaître mes&nbsp;limites</h2>
|
||
<p>Rester dans une position de <em>sachant</em> semble me pousser à des comportements de fermeture d&#8217;esprit. La « sagesse » serait-elle la faculté à se remettre en question ? Mais quid des « fausses vérités » et des <em>avis de surface</em>, de ce que l&#8217;on croit connaître&nbsp;?</p>
|
||
<p>Peut-être que la solution est de connaître mes limites, ou en tout cas de les rechercher et de reconnaître mes zones de&nbsp;flou. </p></content><category term="journal"></category></entry><entry><title>Travail, passion et limites.</title><link href="https://blog.notmyidea.org/travail-passion-et-limites.html" rel="alternate"></link><published>2019-10-25T00:00:00+02:00</published><updated>2019-10-25T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-10-25:/travail-passion-et-limites.html</id><summary type="html">
|
||
<p>Je discutais avec des ami⋅e⋅s brasseurs, cavistes et barmaid du rapport que chacun⋅e entretient avec le travail, et je me suis étonné de voir que notre rapport soit aussi&nbsp;différent.</p>
|
||
<p>Notamment, ce que j&#8217;estime de prime abord comme un <em>travail acharné</em> peut également être analysé sous …</p></summary><content type="html">
|
||
<p>Je discutais avec des ami⋅e⋅s brasseurs, cavistes et barmaid du rapport que chacun⋅e entretient avec le travail, et je me suis étonné de voir que notre rapport soit aussi&nbsp;différent.</p>
|
||
<p>Notamment, ce que j&#8217;estime de prime abord comme un <em>travail acharné</em> peut également être analysé sous l&#8217;angle de la passion, voire même être un trait de personnalité « mono-maniaque » qui explique que certain⋅e⋅s mettent le travail avant tout le reste dans leur&nbsp;vie.</p>
|
||
<p>J&#8217;ai tendance à analyser ça sous l&#8217;angle du « travaillisme » : trouver une certaine forme de fierté au fait de travailler beaucoup (voire trop, selon ma conception&nbsp;personnelle)</p>
|
||
<p>Je me rends compte que, de mon côté, je n&#8217;ai pas qu&#8217;une seule passion, mais plusieurs, et me pose la question de l&#8217;incidence de ces multiples passions sur ma volonté de créer un emploi qui me laisse du temps libre pour pouvoir les vivre&nbsp;toutes.</p></content><category term="journal"></category></entry><entry><title>Ours</title><link href="https://blog.notmyidea.org/ours.html" rel="alternate"></link><published>2019-07-03T00:00:00+02:00</published><updated>2019-07-03T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-07-03:/ours.html</id><summary type="html"><p>J&#8217;ai de plus en plus de mal à garder mon calme dans les situations ou je
|
||
rencontres des humains qui ont des comportements que je trouve déplacés. Je me demande à quel point le fait d&#8217;être maintenant un commerçant impacte ma
|
||
capacité relationnelle&nbsp;générale.</p>
|
||
<p>De manière plus large …</p></summary><content type="html"><p>J&#8217;ai de plus en plus de mal à garder mon calme dans les situations ou je
|
||
rencontres des humains qui ont des comportements que je trouve déplacés. Je me demande à quel point le fait d&#8217;être maintenant un commerçant impacte ma
|
||
capacité relationnelle&nbsp;générale.</p>
|
||
<p>De manière plus large, est-ce normal de tolérer des comportements qu&#8217;on estime anormaux, voire immoraux ? Quand est-ce que la tolérance laisse place a de l&#8217;acceptation de comportements problématiques&nbsp;?</p>
|
||
<p>Suis-je en train de devenir un ours&nbsp;?</p></content><category term="journal"></category></entry><entry><title>Vélo</title><link href="https://blog.notmyidea.org/velo.html" rel="alternate"></link><published>2019-06-27T00:00:00+02:00</published><updated>2019-06-27T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-06-27:/velo.html</id><summary type="html"><p>Depuis quelques semaines j&#8217;ai décidé d&#8217;utiliser le vélo pour aller au boulot. Pas forcement tous les jours, mais dès que les conditions le permettent je n&#8217;hésite&nbsp;pas.</p>
|
||
<p>C&#8217;est un vrai plaisir de se déplacer en deux roues, en quasiment silence. Le trajet mets pas loin de …</p></summary><content type="html"><p>Depuis quelques semaines j&#8217;ai décidé d&#8217;utiliser le vélo pour aller au boulot. Pas forcement tous les jours, mais dès que les conditions le permettent je n&#8217;hésite&nbsp;pas.</p>
|
||
<p>C&#8217;est un vrai plaisir de se déplacer en deux roues, en quasiment silence. Le trajet mets pas loin de 35mn et passe par un parc sur la fin, c&#8217;est un vrai moment de relaxation, et qui me permet de faire une jonction entre ma vie personnelle et le taf à la&nbsp;brasserie.</p></content><category term="journal"></category></entry><entry><title>Un espace des communs Rennais ?</title><link href="https://blog.notmyidea.org/un-espace-des-communs-rennais.html" rel="alternate"></link><published>2019-06-26T00:00:00+02:00</published><updated>2019-06-26T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-06-26:/un-espace-des-communs-rennais.html</id><summary type="html"><p><em>Ce document se veut surtout être quelques notes, et donc revêt un caractère « fouilli » paaaarfaitement assumé. D’ailleurs, ce n&#8217;est que ce que j&#8217;ai bien voulu retenir.&nbsp;Voilà.</em></p>
|
||
<p>Je ressors d&#8217;une discussion avec quelques complices autour de deux idées :
|
||
1. Avoir un espace pour fédérer différentes personnes …</p></summary><content type="html"><p><em>Ce document se veut surtout être quelques notes, et donc revêt un caractère « fouilli » paaaarfaitement assumé. D’ailleurs, ce n&#8217;est que ce que j&#8217;ai bien voulu retenir.&nbsp;Voilà.</em></p>
|
||
<p>Je ressors d&#8217;une discussion avec quelques complices autour de deux idées :
|
||
1. Avoir un espace pour fédérer différentes personnes intéressées par le sujet des <em>communs</em>;
|
||
2. Monter une structure Rennaise pour proposer de l’hébergement de services&nbsp;web.</p>
|
||
<p>Élaborons un&nbsp;peu&#8230;</p>
|
||
<h2 id="1-un-espace-pour-federer">1. Un espace pour&nbsp;fédérer</h2>
|
||
<p>L&#8217;idée qui à été développée est celle d&#8217;avoir un espace (un ou des lieux, à différents moments dans l&#8217;année) pour que les rencontres entre les projets <em>du libre</em> à Rennes puissent se dérouler. Le constat est qu&#8217;il existe différentes structures actuellement en place, mais que a) certaines personnes ne se retrouvent pas dans ces espaces et b) la porosité entre ces différents groupes est assez&nbsp;faible.</p>
|
||
<p>Pour l&#8217;instant pas d&#8217;idée précise de ce qui pourrait être proposé, mais quelques pistes ont été évoquées. l&#8217;envie est de faire un document d&#8217;intention et de proposer à d&#8217;autres de rejoindre le collectif en&nbsp;création.</p>
|
||
<h3 id="frequence">Fréquence</h3>
|
||
<p>Deux pistes ont été&nbsp;évoquées:</p>
|
||
<ul>
|
||
<li>
|
||
<p><strong>Faire des rencontres suffisamment espacées les unes des autres</strong>, pour que leur caractère « exceptionnel » soit une force. Si la fréquence des réunions est assez faible, alors l&#8217;incitation pour y prendre part est peut-être plus grande&nbsp;?</p>
|
||
</li>
|
||
<li>
|
||
<p>ou au contraire, <strong>avoir des rencontres avec une fréquence assez forte</strong>, pour qu&#8217;en cas d&#8217;incapacité à participer il n&#8217;y ait pas trop longtemps à attendre&nbsp;?</p>
|
||
</li>
|
||
</ul>
|
||
<h3 id="charte-ethique">Charte&nbsp;éthique</h3>
|
||
<p>Le fait d&#8217;avoir un <em>code de conduite</em> pour de tels évènements à été discuté, un des arguments évoqués étant le fait qu&#8217;un tel code n&#8217;est pas considéré nécessaire par certaines personnes, puisque les règles évoquées tiennent du bon&nbsp;sens.</p>
|
||
<p>Il a été précisé que l&#8217;établissement de ce type de document a pour objectif de:
|
||
- Faire que des minorités et/ou oppressés se sentent protégés et considérés, et donc bienvenues à ce type d&#8217;évènements;
|
||
- En cas de situations considérées comme problématiques, des personnes référentes soient désignées pour aider à leur&nbsp;résolution</p>
|
||
<h3 id="gouvernance">Gouvernance</h3>
|
||
<p>Le sujet de la gouvernance à été également abordé : pour avoir de tels rendez-vous, peu importe leur nature, il faut que ceux-cis soient organisés. La possibilité d&#8217;avoir des organisat·rices·eurs· tournantes à été&nbsp;proposé.</p>
|
||
<p>Pour&nbsp;:</p>
|
||
<ul>
|
||
<li>Cela permet de ne pas reposer uniquement sur quelques&nbsp;personnes;</li>
|
||
<li>Faire des fiches explicatives qui permettent à tou·te·s de&nbsp;s&#8217;impliquer</li>
|
||
</ul>
|
||
<p>Contre&nbsp;: </p>
|
||
<ul>
|
||
<li>Quand tout le monde est responsable, personne ne&nbsp;l&#8217;est.</li>
|
||
</ul>
|
||
<p>Peut-être que des solutions intermédiaires sont à trouver, en désignant d&#8217;une fois sur l&#8217;autre les personnes qui s’occupent du prochain rendez-vous, par&nbsp;exemple.</p>
|
||
<h2 id="2-hebergement-de-services-web">2. Hébergement de services&nbsp;Web</h2>
|
||
<p>On a discuté très rapidement de la possibilité de monter une structure pour faire de l’hébergement de services web sur Rennes. Le sujet n&#8217;a pas été vraiment développé, mais la question de la relation entre avoir un espace pour fédérer (le 1.) et être un hébergeur de service (le 2.) a été rapidement&nbsp;abordé.</p>
|
||
<p>Faut-il avoir une seule et même structure / groupe de personnes pour ces deux projets ? Dans le cas ou l&#8217;un s&#8217;arrête, entraînerait-il l&#8217;autre dans sa « chute » ? Est-il logique de lier les deux&nbsp;?</p>
|
||
<h2 id="et-donc">Et donc&nbsp;?</h2>
|
||
<p>Et donc c&#8217;était bien chouette de prendre un peu le temps de remettre le nez dans la vie libriste Rennaise ! Ravi de voir une dynamique prendre forme, on verra bien ou ça mène&nbsp;:-)</p></content><category term="journal"></category></entry><entry><title>Brasserie - petit bilan, après un an d’existence</title><link href="https://blog.notmyidea.org/un-an.html" rel="alternate"></link><published>2019-05-21T00:00:00+02:00</published><updated>2019-05-21T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2019-05-21:/un-an.html</id><summary type="html"><h1 id="la-brasserie-du-vieux-singe-a-un-an">La brasserie du Vieux Singe a un an&nbsp;!</h1>
|
||
<p>On a l&#8217;impression que c&#8217;était hier tellement le temps passe vite, mais ça fait un an que notre brasserie existe&nbsp;!</p>
|
||
<p>Alors on lève un peu la tête du guidon question de voir ce qu&#8217;on a accompli durant cette première …</p></summary><content type="html"><h1 id="la-brasserie-du-vieux-singe-a-un-an">La brasserie du Vieux Singe a un an&nbsp;!</h1>
|
||
<p>On a l&#8217;impression que c&#8217;était hier tellement le temps passe vite, mais ça fait un an que notre brasserie existe&nbsp;!</p>
|
||
<p>Alors on lève un peu la tête du guidon question de voir ce qu&#8217;on a accompli durant cette première année, et de faire un petit bilan&nbsp;:-)</p>
|
||
<h2 id="quelques-dates-chiffres">Quelques dates <span class="amp">&amp;</span>&nbsp;chiffres</h2>
|
||
<p>Pour se donner un peu de perspective, voici quelques dates clés de cette première année&nbsp;:</p>
|
||
<ul>
|
||
<li>Novembre 2017 : immatriculation de&nbsp;l&#8217;entreprise</li>
|
||
<li>Décembre 2017 : on a les clés&nbsp;!</li>
|
||
<li>Décembre 2017 à Mars 2018 : travaux, installation et divers&nbsp;bricolages</li>
|
||
<li>Mars 2018 : premier&nbsp;brassin</li>
|
||
<li>Mai 2018 : premières ventes&nbsp;!</li>
|
||
<li>Août 2018 : vacances&nbsp;:-)</li>
|
||
<li>Septembre 2018 : inauguration de la brasserie <span class="amp">&amp;</span> premier brassin&nbsp;unique</li>
|
||
<li>Décembre 2018 : second brassin&nbsp;unique</li>
|
||
<li>Mars 2019 : on se rémunère&nbsp;!</li>
|
||
</ul>
|
||
<p>Au moment d’écrire ces lignes, à la mi Mai 2019, on en est à notre 43ème brassin, on a travaillé sur 4 nouvelles bières, on a dû laver pas loin de 300 fûts, ouverts 700 sacs de malt… et on vous a fait boire la tasse&nbsp;;-)</p>
|
||
<p>Petit retour en&nbsp;arrière…</p>
|
||
<h2 id="travaux-installation">Travaux <span class="amp">&amp;</span>&nbsp;installation</h2>
|
||
<p>En arrivant dans nos locaux, on a d’abord dû réaliser quelques travaux d’aménagement : une grande partie de l&#8217;espace était utilisé en bureaux or on a surtout besoin de place dans la partie « prod&nbsp;».</p>
|
||
<p>On a rajouté à notre local une tranchée pour l’évacuation des eaux usées, une chambre chaude pour la refermentation en bouteilles, ainsi que quelques gros points d’électricité et de plomberie (circuit de refroidissement des fermenteurs et plusieurs arrivées&nbsp;d’eau).</p>
|
||
<p>On a profité d’être sur une zone artisanale pour récupérer quelques palettes perdues chez nos voisins et les transformer en bar, tabourets et étagères, question de pouvoir vous accueillir de manière un peu sympathique&nbsp;!</p>
|
||
<p><img alt="Photo du bar" src="/images/un-an/bar.jpg"></p>
|
||
<p>Une fois les travaux d’aménagements terminés, on a reçu les cuves. Un moment très attendu (et un peu flippant, oui). On a d’abord reçu les fermenteurs, debout, qu’on a pu décharger au chariot élévateur, puis les cuves de brassage, la ligne d’embouteillage et enfin notre cuve de ressucrage et carbonatation. Cette dernière est arrivée couchée, on a donc du la relever à l’aide d’une grue. Vous voyez les gouttes de sueur perler sur nos fronts&nbsp;?</p>
|
||
<p><img alt="Photo du levage du fermenteur avec la grue" src="/images/un-an/dechargement.jpg"></p>
|
||
<p>Quasiment aucun problème pour décharger les fermenteurs, au final. Le plus difficile a été le déchargement de notre ligne d’embouteillage, assez lourde, pour laquelle on a eu quelques déconvenues. On a la chance d’avoir sur la zone <a href="https://www.jfblevage.fr/">une entreprise de levage très arrangeante</a> qui nous a permis de décharger ça correctement, nous enlevant une belle épine du&nbsp;pied.</p>
|
||
<p>A peine les fermenteurs installés, on réceptionnait les cuves de brassage. Les Anglais de <a href="https://www.pbcbreweryinstallations.com/"><span class="caps">PBC</span></a> sont venus sur place pour terminer l’installation et nous assister sur notre premier brassin sur cette nouvelle brasserie dont on est plutôt satisfaits.
|
||
L&#8217;avantage de ce matériel c&#8217;est que c&#8217;est la <span class="caps">2CV</span> du brasseur : tout est manuel et facile à démonter <span class="amp">&amp;</span> remplacer en cas de soucis (ce qu&#8217;on a pas tardé à vérifier&nbsp;!)</p>
|
||
<h2 id="premiers-brassins">Premiers&nbsp;brassins</h2>
|
||
<p>Sur nos premiers brassins, on a décidé d’utiliser la brasserie à la moitié de sa capacité. Après tout, la moitié c&#8217;était déjà dix fois plus gros que ce qu&#8217;on avait l&#8217;habitude de faire jusqu&#8217;alors avec notre petite brasserie&nbsp;100L.</p>
|
||
<p>On est donc partis sur des brassins de 800 litres. Les premiers brassins se sont vraiment bien déroulés : 7 heures de brassage <span class="amp">&amp;</span> nettoyage pour 800L de&nbsp;moût.</p>
|
||
<p>Au moment de passer nos recettes à l&#8217;échelle, on a quand même fait quelques petits changements techniques, dont je vous passe les détails&nbsp;ici.</p>
|
||
<p>Et puis, au fur et à mesure de l’année, les recettes et procédés pour nos bières « permanentes » ont un peu bougé également (modification de l&#8217;eau de brassage, changement des temps <span class="amp">&amp;</span> températures pour l&#8217;ajout du houblon lors du <em>dry hopping</em>)</p>
|
||
<h2 id="preventes-puis-ventes">Préventes, puis&nbsp;ventes</h2>
|
||
<p>En parallèle du brassage, on faisait nos premières ventes avec notre système de préventes en&nbsp;ligne.</p>
|
||
<p>Le deal était assez simple : vous achetez les bières avant qu&#8217;elles ne soit brassées, et vous passez les chercher à la brasserie une fois&nbsp;prêtes.</p>
|
||
<p>Double avantage pour nous : une avance de trésorerie non négligeable (on a vendu nos trois premiers brassins en vente directe !) et la possibilité de faire visiter la brasserie quand les gens passent chercher leurs bières : un bon moyen de se&nbsp;rencontrer.</p>
|
||
<p>Notre retour sur ces préventes est vraiment&nbsp;positif. </p>
|
||
<p>Une fois les premiers brassins terminés, et les préventes écoulées, il fallait commencer à mettre en place un circuit de distribution pour les gens qui ne viennent pas nous voir à la&nbsp;brasserie.</p>
|
||
<p>Et là, <em>le double effet kiss-cool</em> de notre campagne de préventes : le bouche-à-oreilles a fait que des clients nous ont appelé directement avec l&#8217;envie de travailler avec nous ! Résultat : on se retrouve aujourd&#8217;hui avec un maillage de petits et moyens clients qui nous commandent de la bière plus ou moins&nbsp;régulièrement.</p>
|
||
<p>On est hyper contents de travailler avec autant de clients atypiques qui font vivre un monde qui nous parle : plusieurs cafés associatifs, des festivals engagés, des magasins de producteurs, des épiceries associatives, des groupements d’achats. On n&#8217;aurait vraiment pas rêvé mieux&nbsp;!</p>
|
||
<p>On a également trois petites tireuses et des gobelets, qui nous permettent de vendre des fûts à des particuliers et associations pour des petits&nbsp;évènements.</p>
|
||
<p>En plus de ces ventes directes, on a fait le choix de passer par des petits distributeurs pour que notre bière se retrouve à des endroits où on ne va pas livrer (la Bretagne en dehors de l&#8217;Ille-et-Vilaine par&nbsp;ex).</p>
|
||
<p>On s&#8217;est également mis à travailler avec un transporteur pour faire des&nbsp;envois.</p>
|
||
<h2 id="organisation-du-temps">Organisation du&nbsp;temps</h2>
|
||
<p>Autant pour fabriquer de la bière on avait un peu d’expérience, autant pour faire tourner une entreprise on avait tout à découvrir&nbsp;! </p>
|
||
<p>On passe beaucoup de temps à faire les taches administratives (téléphone, ordinateur) qu’on n&#8217;avait pas imaginées à l’origine. Ça représente environ la moitié de notre temps de travail&nbsp;!</p>
|
||
<p>Au final, on ne travaille tous les deux ensemble qu&#8217;assez rarement : on alterne sur la <em>production</em> (brassage, mise en bouteilles, mise en fûts, et surtout nettoyage !) d’une semaine sur l’autre ; et quand on n&#8217;est pas « de prod », on s’est réparti les tâches administratives : Fred s’occupe de la partie comptabilité et des fournisseurs ; Alexis des ventes, de la communication et de la gestion du&nbsp;stock.</p>
|
||
<p>En pratique ça fonctionne plutôt bien, on se fait un (indispensable !) point de synchronisation tous les lundi matin, pour lequel il faut compter au moins&nbsp;3h.</p>
|
||
<p>Le problème, c’est qu’on reste un peu la tête dans le guidon. On essaie bien de prendre du recul, mais le boulot, lui, n’attend pas&nbsp;!</p>
|
||
<p>Et c’est là que les vacances prennent tout leur sens. Une des forces d’être à Rennes c’est qu’au mois d’Août, il ne se passe absolument rien. Le pied ! Allez hop, en vacances&nbsp;!</p>
|
||
<h2 id="la-place-de-lexperimentation">La place de&nbsp;l’expérimentation</h2>
|
||
<p>Pour nous, faire de la bière est aussi un moyen d’expérimenter. Expérimentations qui parfois débouchent sur des brassins uniques, quand on trouve que ça vaut le coup (ou quand on teste direct en gros&nbsp;!)</p>
|
||
<p>Et quand on passe des tests à l’échelle, (de 20L à 1500L), on est moyennement rassurés&nbsp;!</p>
|
||
<p>Après quelques brassins validés, on est un peu plus relax sur le sujet, et on a mis en place de quoi faire des expérimentations à petite échelle de manière simple : vu qu&#8217;on produit du moût toutes les semaines, on en utilise une partie pour faire quelques tests : changement de levure, adjonctions, changement des températures de fermentation,&nbsp;etc.</p>
|
||
<p>Ah ça, c’est pas les idées qui nous manquent :-) Et c&#8217;est une super manière&nbsp;d&#8217;expérimenter.</p>
|
||
<p><img alt="Étiquette de la Sobacha, une lager avec une infusion de sarrasin torréfié" src="/images/un-an/sobacha.png"></p>
|
||
<p><img alt="Étiquette de Monstrueuse Normalité, une New England IPA" src="/images/un-an/monstrueuse-normalite.png"></p>
|
||
<p><img alt="Étiquette de Chaînon Manquant, une Sour Pale Ale avec du Kiwi" src="/images/un-an/chainon-manquant.png"></p>
|
||
<h2 id="ouverture-au-public-evenements-et-equilibre">Ouverture au public, évènements et&nbsp;équilibre</h2>
|
||
<p>On a pris le parti d&#8217;ouvrir le magasin toutes les fins de semaine (le jeudi et vendredi de 17h à 19h) et on est hyper contents de faire visiter la brasserie aux personnes qui passent de temps à autre. Pour nous, ça fait partie des plaisirs du métier. Par contre, on avait clairement sous estimé le temps que ça nous prendrait. On accueille beaucoup et les gens sont curieux. La fabrication de bière reste encore aujourd’hui quelque chose de nouveau pour la plupart, et il faut satisfaire cette curiosité (il faut plus de brasseries&nbsp;!).</p>
|
||
<p>Ce qui se passe en ce moment sur la scène brassicole est génial : beaucoup de nouvelles brasseries proposent des produits exceptionnels, et les évènements se multiplient aux quatre coins de la France. On adore partager, goûter, discuter, mais on ne pensait pas être autant sollicités par des évènements extérieurs, souvent sur des week-end, et parfois loin. <strong>On souhaite garder un équilibre entre notre vie personnelle et notre vie professionnelle</strong>. Aller aux évènements aussi par plaisir. Être partout est probablement un des maux de notre temps ;-) À force de voir des brasseurs exténués, il y a de quoi se poser des questions sur la pérennité sur le long terme d’un rythme aussi&nbsp;effréné.</p>
|
||
<p>Notre choix, c’est celui d’être fiers de nos bières, mais également celui de créer un outil pour nos vies (la brasserie) qui leur rende service. Penser son travail de cette manière nous permet de garder les pieds sur&nbsp;terre.</p>
|
||
<h2 id="bref">Bref…</h2>
|
||
<p>…Voilà pour le petit tour d&#8217;horizon de cette année écoulée. Plein de super choses dans les mois à venir, on vous donne des nouvelles très bientôt&nbsp;!</p></content><category term="journal"></category></entry><entry><title>De Mozilla à la Brasserie du Vieux Singe</title><link href="https://blog.notmyidea.org/de-mozilla-a-la-brasserie-du-vieux-singe.html" rel="alternate"></link><published>2018-05-27T00:00:00+02:00</published><updated>2018-05-27T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2018-05-27:/de-mozilla-a-la-brasserie-du-vieux-singe.html</id><summary type="html"><p><em>Ce weekend avait lieu <a href="https://sudweb.fr/2018/">SudWeb</a> « la conférence Web surtout humaine », ou on m&#8217;a proposé de venir parler de ma reconversion professionnelle, ou comment un passionné de Logiciels Libres choisit de créer une petite brasserie&nbsp;artisanale.</em></p>
|
||
<p><em>Certaines parties de ce que je voulais transmettre sont passées à la trappe, alors …</em></p></summary><content type="html"><p><em>Ce weekend avait lieu <a href="https://sudweb.fr/2018/">SudWeb</a> « la conférence Web surtout humaine », ou on m&#8217;a proposé de venir parler de ma reconversion professionnelle, ou comment un passionné de Logiciels Libres choisit de créer une petite brasserie&nbsp;artisanale.</em></p>
|
||
<p><em>Certaines parties de ce que je voulais transmettre sont passées à la trappe, alors que d&#8217;autres ont pris plus de place que prévu. J&#8217;avais donc envie de reprendre mes notes pour les transformer en billet de blog, question d&#8217;élaborer sur le&nbsp;sujet.</em></p>
|
||
<hr>
|
||
<p>J&#8217;ai toujours été motivé par mes passions. Quand j&#8217;ai commencé à travailler professionnellement, je me suis rendu compte que même si je faisais quasiment la même chose qu&#8217;auparavant, ça n&#8217;avait plus le même goût. J&#8217;étais maintenant <em>obligé</em> de le faire, et je n&#8217;en tirais pas le même&nbsp;plaisir.</p>
|
||
<p>Quand j&#8217;étais plus jeune au lycée j&#8217;écrivais des programmes en <em>Visual Basic</em> que je partageais en ligne sur mon site en <code>.free.fr</code>. Programmes que probablement personne n&#8217;a lu, mais l&#8217;intention était bel et bien celle de partager mes créations, et d&#8217;échanger à leur&nbsp;propos.</p>
|
||
<p>Cette culture du partage — celle du logiciel libre — est celle qui&nbsp;m&#8217;anime.</p>
|
||
<p>Quelques années plus tard, je découvre le langage de programmation Python, et avec lui toute une communauté, mue par ces mêmes valeurs de partage et d&#8217;amélioration de nos pratiques. Puis je rencontre le Logiciel Libre, avec l&#8217;écriture d&#8217;un programme (<a href="https://getpelican.com">pelican</a>) qui reste encore largement utilisé aujourd&#8217;hui. Autant dire que c&#8217;est une bonne claque que de voir des inconnus contribuer à un bout de code qu&#8217;eux aussi jugent&nbsp;utile.</p>
|
||
<p>À la fin de mes études, alors que je reste passionné par le développement logiciel, je ne veux ni travailler pour l&#8217;industrie, ni pour la finance. Je songe même déjà à cette époque à changer de métier (avant même d&#8217;avoir commencé !). Coup de bol, une structure qui m&#8217;est chère cherche des développeurs Python: Mozilla. Sans trop y croire, je passe une série d&#8217;entretiens qui se déroulent bien (!) et je commence quelques mois plus tard à travailler pour cette organisation incroyable, porteuse d&#8217;espoir et de toute une symbolique pour&nbsp;moi.</p>
|
||
<p>Je bosse sur du Logiciel Libre, en Python, en télétravail parfois, avec une bonne paie, sans parler du côté prestigieux.&nbsp;Grisant.</p>
|
||
<p>Mais au fur et à mesure je découvre l&#8217;envers du décors: une méritocratie ancrée et assumée, une hiérarchie de plus en plus importante, menant à une lourdeur administrative assez présente. À ajouter à la barrière de la langue, et aux différences culturelles. Finalement tout n&#8217;est pas rose&nbsp;ici.</p>
|
||
<p>Je décide alors de (je pense) faire un de mes meilleurs choix de vie à ce jour: passer aux 4/5èmes. Je récupère tous mes vendredis. Des weekends de 3 jours, toutes les semaines. Un espace précieux pour me reposer, et pour rêver un&nbsp;peu.</p>
|
||
<p>C&#8217;est à ce moment que Fred, un ami de longue date, en revenant du Québec (ou les brasseries sont légion), me propose de faire de la bière avec lui. Moi qui ne savais même pas qu&#8217;il était <em>possible</em> de faire de la bière. On tente donc l&#8217;expérience, et nos premières expériences sont des journées bien <em>funky</em>, à faire toutes les erreurs&nbsp;possibles.</p>
|
||
<p>Peu à peu, on découvre un nouveau monde: celui des brasseurs amateurs. De nouvelles compétences sont nécessaires, de la physique à la biochimie. On se met à rencontrer des professionnels, des passionnés, à échanger sur les forums. On se forme, petit à petit. Tout comme il y a la communauté des gens qui font du Python, il y a la communauté des gens qui font de la bière. Pas encore autant fédérés, ça semble balbutiant alors mais la passion elle est bien&nbsp;présente.</p>
|
||
<p>Tout comme le monde du Logiciel Libre est constitué autour d&#8217;un ennemi commun (les <span class="caps">GAFA</span>), le monde de la bière artisanale à la sien: les brasseries industrielles, qui uniformisent les goûts et les&nbsp;processus.</p>
|
||
<p>Je continue en parallèle mon travail chez Mozilla, pendant 4 années. Et puis un jour, une annonce d&#8217;arrêt d&#8217;un projet sur lequel je travaillais me fait réaliser que cette situation m&#8217;épuise. La fameuse goutte de&nbsp;trop.</p>
|
||
<p>Je décide alors de partir, de faire une pause, sans trop savoir ce que l&#8217;avenir me réserve. Une petite période de blanc de deux mois. Le regard des autres est parfois culpabilisant. Mes parents me demandent si « je ne veux pas attendre encore un peu ». La transition me fait peur, mais je choisis quand même de troquer mon confort matériel pour de la&nbsp;cohérence.</p>
|
||
<p>Petit à petit, l&#8217;idée de monter ce qui est maintenant devenu <a href="https://www.vieuxsinge.com">La Brasserie du Vieux Singe</a> se pose en évidence. Mais monter une brasserie ce n&#8217;est pas uniquement faire de la bière: c&#8217;est se mettre d&#8217;accord sur des valeurs, trouver comment les défendre, monter un projet pour, et tenir le&nbsp;cap.</p>
|
||
<p>Quelques mois après mon départ, on se retrouve donc à parler de ces valeurs de partage, de documentation, de goût. De gouvernance et de collaboration aussi.
|
||
Dans nos pratiques courantes, on décide d&#8217;intégrer du temps pour documenter la vie de la&nbsp;brasserie.</p>
|
||
<p>À titre d&#8217;exemple, nos étiquettes contiennent l&#8217;ensemble des ingrédients que l&#8217;on utilise de la manière la plus détaillée possible. On travaille aussi sur un projet de laveuse de fûts, qui sera publié sous licence libre, avec l&#8217;idée de pouvoir, petit à petit, constituer un ensemble d&#8217;outils utiles à tous les brasseurs, et peut être même réussir à favoriser les échanges entre toutes ces&nbsp;personnes.</p>
|
||
<p>Nous sommes deux brasseurs, deux chefs d&#8217;entreprise, mais aussi deux développeurs. Nos compétences de développeurs nous sont utiles quotidiennement: pour notre laveuse de fûts, pour nos créations de recettes (j&#8217;ai découvert la puissance des tableurs !), pour notre site de préventes, notre site Web, nos outils du quotidien. On se rend compte qu&#8217;il s&#8217;agit de compétences&nbsp;précieuses.</p>
|
||
<p>Mais monter une entreprise, c&#8217;est aussi assumer une partie administrative. Vous vous rappelez cette histoire de réactions face aux activités subordonnées ? Et bien quand je fais mes déclarations aux douanes, ce n&#8217;est pas de gaîté de cœur. Je sais par contre pourquoi je le fais: ce sont les règles du jeu. Des obligations, mais peut-être moins de coercition. J&#8217;y trouve plus de&nbsp;sens.</p>
|
||
<p>Et, si je n&#8217;avais pas réduit mon temps de travail, j&#8217;aurais peut-être loupé la découverte de ce nouveau monde, celui qui me passionne&nbsp;aujourd&#8217;hui.</p>
|
||
<p>Alors je vous invite à vous poser la question — indispensable — de vos valeurs: qu&#8217;est-ce que vous souhaitez faire ? Qu&#8217;est-ce qui vous anime ? Et peut-être à aménager du temps pour explorer vos&nbsp;envies. </p></content><category term="journal"></category></entry><entry><title>Groupement d’achats & partage d’expérience</title><link href="https://blog.notmyidea.org/groupement-dachats-partage-dexperience.html" rel="alternate"></link><published>2018-03-03T00:00:00+01:00</published><updated>2018-03-03T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2018-03-03:/groupement-dachats-partage-dexperience.html</id><summary type="html"><p>Il y a quelques années, on s&#8217;est motivé entre copains copines pour créer un groupement&nbsp;d&#8217;achat.</p>
|
||
<p>L&#8217;idée est&nbsp;simple:</p>
|
||
<ul>
|
||
<li>commander en gros, pour faire baisser les&nbsp;prix</li>
|
||
<li>se passer d&#8217;intermédiaires et favoriser les circuits&nbsp;courts</li>
|
||
<li>aller à la rencontre des producteurs locaux et&nbsp;échanger</li>
|
||
</ul>
|
||
<p>Notre groupement …</p></summary><content type="html"><p>Il y a quelques années, on s&#8217;est motivé entre copains copines pour créer un groupement&nbsp;d&#8217;achat.</p>
|
||
<p>L&#8217;idée est&nbsp;simple:</p>
|
||
<ul>
|
||
<li>commander en gros, pour faire baisser les&nbsp;prix</li>
|
||
<li>se passer d&#8217;intermédiaires et favoriser les circuits&nbsp;courts</li>
|
||
<li>aller à la rencontre des producteurs locaux et&nbsp;échanger</li>
|
||
</ul>
|
||
<p>Notre groupement dessert actuellement 18 foyers et une 60aine de&nbsp;personnes.</p>
|
||
<p>Au fur et à mesure de la vie du groupement, on a développé quelques outils pour se simplifier la vie. Voici un retour d&#8217;expérience et quelques astuces / outils, au cas où l&#8217;envie vous prenne à vous aussi&nbsp;:)</p>
|
||
<h1 id="organisation">Organisation</h1>
|
||
<p>On organise environs trois ou quatre distributions par an. Le <em>modus operandi</em> est le&nbsp;suivant:</p>
|
||
<ul>
|
||
<li>chaque product·eur·rice à un·e référent·e, qui s&#8217;occupe de faire le&nbsp;lien;</li>
|
||
<li>une personne est désignée pour coordonner la&nbsp;distribution;</li>
|
||
<li>4 semaines avant la distribution, les référent·e·s mettent à jour les prix / produits dans le tableau de&nbsp;commandes;·e·</li>
|
||
<li>3 semaines avant la distribution, les commandes sont&nbsp;ouvertes;</li>
|
||
<li>2 semaines avant la distribution, les commandes sont&nbsp;closes;</li>
|
||
<li>Les référent·e·s ont ensuite deux semaines pour récupérer les commandes pour la&nbsp;distribution</li>
|
||
</ul>
|
||
<h1 id="quels-produits">Quels produits&nbsp;?</h1>
|
||
<p>On essaye d&#8217;avoir uniquement des produits qui se conservent (on a également quelques autres produits plus frais, mais avec d&#8217;autres&nbsp;modalités).</p>
|
||
<p>Entre autres: bières, légumes secs, conserves, jus, miel, pâtes, semoule, café, vinaigres, pommes de terre, oignons, huiles,&nbsp;farines.</p>
|
||
<p>On essaye de faire du local puis du bio au plus proche plutôt que de trouver nécessairement les prix les plus bas. C&#8217;est une discussion qui revient assez
|
||
souvent, et donc un point à évoquer lors de la création pour avoir une posture
|
||
claire sur le sujet (tout le monde n&#8217;est pas animé par la même éthique&nbsp;!).</p>
|
||
<h1 id="paiements">Paiements</h1>
|
||
<p>Pour les paiements, on utilise autant que possible des chèques. Chaque référent·e paye la·le product·rice·eur en son nom, et lui demande d&#8217;attendre la date de la distribution pour l&#8217;encaissement. La plupart des producteurs acceptent d&#8217;être payés sous&nbsp;quinzaine.</p>
|
||
<p>Le jour de la distribution, tout le monde apporte son chéquier. Nous avons mis
|
||
en place une moulinette qui s&#8217;occupe de faire la répartition des chèques automatiquement, chaque membre se retrouve à faire en moyenne un ou deux&nbsp;chèques.</p>
|
||
<p>Chaque référent·e est ainsi remboursé·e de la somme avancée, et chaque
|
||
membre du groupement d&#8217;achat paye ce qu&#8217;il doit payer. Nous n&#8217;avons
|
||
volontairement pas de structure juridique et pas de compte en banque. Les
|
||
paiements s&#8217;effectuent directement entre&nbsp;nous.</p>
|
||
<h1 id="transports">Transports</h1>
|
||
<p>Chaque référent·e commande les produits, puis ensuite s&#8217;occupe de les rapatrier. À Rennes, on a la chance d&#8217;avoir pas mal de producteurs aux alentours, donc c&#8217;est assez&nbsp;simple.</p>
|
||
<p>Le mieux est de ramener les produits juste un peu avant la distribution au lieu de distribution, ça permet d&#8217;éviter de les stocker trop longtemps, et d&#8217;éviter aux producteurs d&#8217;attendre trop longtemps avant d&#8217;encaisser les&nbsp;chèques.</p>
|
||
<p>Pour les grosses commandes, les voitures se remplissent bien, mais ma petite Clio suffit, que ce soit dit&nbsp;!</p>
|
||
<h1 id="la-distribution">La&nbsp;distribution</h1>
|
||
<p>Un peu en amont de la distribution, il faut organiser l&#8217;espace. Des tas par membre sont constitués pour faciliter les choses le jour de la&nbsp;distribution.</p>
|
||
<p>Le jour même, on se retrouve, on charge ses marchandises, on échange quelques chèques et on papote ! On en profite&nbsp;pour:</p>
|
||
<ul>
|
||
<li>discuter de la date de la prochaine&nbsp;distribution;</li>
|
||
<li>trouver une nouvelle personne pour la&nbsp;coordonner;</li>
|
||
<li>discuter de nouveaux&nbsp;produits;</li>
|
||
<li>refaire le&nbsp;monde;</li>
|
||
<li>changer de référents pour les&nbsp;producteurs.</li>
|
||
</ul>
|
||
<p>Et c&#8217;est reparti pour un tour&nbsp;;)</p>
|
||
<h1 id="nos-outils">Nos&nbsp;outils</h1>
|
||
<p>On utilise un tableur en ligne pour partager les prix et prendre les commandes. On a essayé d&#8217;utiliser <em>ethercalc</em> au début mais ça ne fonctionnait pas pour nous à l&#8217;époque (trop de petits bugs). On a donc préféré utiliser Google docs&nbsp;(ouch).</p>
|
||
<p>Il est d&#8217;ailleurs possible d&#8217;y intégrer de nouvelles fonctionnalités assez facilement, du coup Fred et Rémy ont planché sur un moyen d&#8217;automatiser la répartition des chèques (qu&#8217;on faisait dans un premier temps à la main - assez&nbsp;péniblement).</p>
|
||
<p>Le système n&#8217;est pas parfait mais fonctionne quand même assez bien&nbsp;!</p>
|
||
<p>Quelques ressources,&nbsp;donc:</p>
|
||
<ul>
|
||
<li><a href="https://gist.github.com/almet/8c77fafc9e487c02ded852ec4a91ae16">le code pour faire la répartition des&nbsp;chèques</a></li>
|
||
<li><a href="https://docs.google.com/spreadsheets/d/1bnPRSvf2Q2RDxKerWnEqUyJjuCFePnVMq6pWo8LeA_k/edit?usp=sharing">une version « à remplir » de notre tableau de commandes</a> (le mieux est d&#8217;en faire une copie&nbsp;!).</li>
|
||
</ul>
|
||
<p>Bon groupement d&#8217;achat&nbsp;;)</p></content><category term="code"></category></entry><entry><title>Webnotes</title><link href="https://blog.notmyidea.org/webnotes.html" rel="alternate"></link><published>2018-02-25T00:00:00+01:00</published><updated>2018-02-25T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2018-02-25:/webnotes.html</id><summary type="html"><p>Quand je navigue en ligne, j&#8217;aime bien prendre des notes sur ce que je lis. C&#8217;est utile pour les retrouver plus tard. Il existe quelques outils pour ce genre de cas, mais j&#8217;ai vraiment eu du mal à trouver un outil qui faisais ce que je voulais …</p></summary><content type="html"><p>Quand je navigue en ligne, j&#8217;aime bien prendre des notes sur ce que je lis. C&#8217;est utile pour les retrouver plus tard. Il existe quelques outils pour ce genre de cas, mais j&#8217;ai vraiment eu du mal à trouver un outil qui faisais ce que je voulais, de la manière que je voulais, c&#8217;est à&nbsp;dire:</p>
|
||
<ul>
|
||
<li>enregistrer une sélection de texte ainsi que son contexte: heure, site&nbsp;web.</li>
|
||
<li>fonctionner sur&nbsp;Firefox;</li>
|
||
<li>stocker mes notes à un endroit que je contrôle (ce sont mes données, après tout&nbsp;!)</li>
|
||
<li>rester en dehors de mon chemin: je suis en train de lire, pas en train d&#8217;organiser mes&nbsp;notes.</li>
|
||
<li>automatiquement partager les notes sur une page&nbsp;web.</li>
|
||
</ul>
|
||
<p>J&#8217;ai donc pris un peu de temps pour fabriquer mon outil de prises de notes, que j&#8217;ai baptisé « Webnotes ». C&#8217;est <a href="https://addons.mozilla.org/en-US/firefox/addon/wwebnotes/">une extension Firefox</a>, qui se configure assez simplement, et qui stocke les données dans une instance de <a href="http://kinto-storage.org/">Kinto</a>.</p>
|
||
<p><img src="https://github.com/almet/webnotes/blob/master/webnotes.gif?raw=true" /></p>
|
||
<p>C&#8217;est aussi simple que sélectionner du texte, faire « clic droit » puis « save as webnote », entrer un tag et le tour est joué&nbsp;!</p>
|
||
<p>Mes notes sont disponibles <a href="https://notes.notmyidea.org">sur notes.notmyidea.org</a>, et voici <a href="https://github.com/almet/webnotes">le lien vers les sources</a>, si ça vous intéresse de regarder comment ça fonctionne&nbsp;!</p></content><category term="code"></category></entry><entry><title>Faire moins</title><link href="https://blog.notmyidea.org/faire-moins.html" rel="alternate"></link><published>2018-01-25T00:00:00+01:00</published><updated>2018-01-25T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2018-01-25:/faire-moins.html</id><summary type="html"><p>L&#8217;an dernier, j&#8217;ai décidé de faire moins de choses, ou plus exactement d&#8217;arrêter de faire de nouvelles choses. Choix assez difficile: j&#8217;aime découvrir de nouvelles pratiques, échanger sur des sujets que je connais pas, et surtout je crois que découvrir de nouvelles pratiques (sans nécessairement creuser …</p></summary><content type="html"><p>L&#8217;an dernier, j&#8217;ai décidé de faire moins de choses, ou plus exactement d&#8217;arrêter de faire de nouvelles choses. Choix assez difficile: j&#8217;aime découvrir de nouvelles pratiques, échanger sur des sujets que je connais pas, et surtout je crois que découvrir de nouvelles pratiques (sans nécessairement creuser un sujet en particulier) est l&#8217;occasion de contribuer à éviter notre société&nbsp;d&#8217;experts.</p>
|
||
<p>Le hic, c&#8217;est que trop, c&#8217;est trop. J&#8217;ai donc décidé d&#8217;arrêter, tout simplement, de faire de nouvelles choses, et puis avec le temps j&#8217;ai même arreté de faire des choses que j&#8217;avais commencé à faire (par exemple de l&#8217;escalade), me libérant du&nbsp;temps.</p>
|
||
<p>Enfin ! Je retrouve ce précieux temps. Je retrouve ces moments d&#8217;ennui. Oui, je comprends bien que ça puisse parraître fou de voir quelqu&#8217;un se réjouir de son ennui… Cet ennui me permet de creuser de nouvelles idées, de reprendre ce bouquin qu&#8217;on avait laissé tomber sans trop de&nbsp;raison.</p>
|
||
<p>Et surtout, c&#8217;est se retrouver à contrôler son&nbsp;engagement.</p></content><category term="journal"></category></entry><entry><title>NEIPA #3</title><link href="https://blog.notmyidea.org/neipa-3.html" rel="alternate"></link><published>2017-12-29T00:00:00+01:00</published><updated>2017-12-29T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2017-12-29:/neipa-3.html</id><summary type="html"><p><em>Voici quelques prises durant un de mes brassins. L&#8217;idée est de pouvoir les relire et m&#8217;améliorer au fur et à&nbsp;mesure.</em></p>
|
||
<p>Test autour d&#8217;une New England Pale Ale; Cette fois ci avec du Mosaic et du Citra, durant une collab&#8217; avec&nbsp;Heiko.</p>
|
||
<h1 id="objectifs">Objectifs:</h1>
|
||
<ul>
|
||
<li>Brasser une nouvelle <span class="caps">NEIPA …</span></li></ul></summary><content type="html"><p><em>Voici quelques prises durant un de mes brassins. L&#8217;idée est de pouvoir les relire et m&#8217;améliorer au fur et à&nbsp;mesure.</em></p>
|
||
<p>Test autour d&#8217;une New England Pale Ale; Cette fois ci avec du Mosaic et du Citra, durant une collab&#8217; avec&nbsp;Heiko.</p>
|
||
<h1 id="objectifs">Objectifs:</h1>
|
||
<ul>
|
||
<li>Brasser une nouvelle <span class="caps">NEIPA</span> en appliquant les trouvailles des deux premières&nbsp;versions;</li>
|
||
<li>Hop stand de&nbsp;40mn;</li>
|
||
<li>Contrôle du pH à&nbsp;5.2;</li>
|
||
<li>Refroidissement dans&nbsp;l&#8217;évier;</li>
|
||
<li>Ajouter plus&nbsp;d&#8217;avoine;</li>
|
||
<li>Faire un mash&nbsp;out;</li>
|
||
<li>Augmenter un peu la quantité de&nbsp;grain.</li>
|
||
</ul>
|
||
<h1 id="recette">Recette:</h1>
|
||
<p><span class="caps">DI</span>: 1055 (atteint)
|
||
pH: 5.2 (5.4&nbsp;mesuré)</p>
|
||
<h2 id="grains">Grains:</h2>
|
||
<ul>
|
||
<li>75% de Pale&nbsp;Ale</li>
|
||
<li>12.5% de&nbsp;blé</li>
|
||
<li>12.5% flocons&nbsp;d&#8217;avoine</li>
|
||
</ul>
|
||
<h2 id="houblons">Houblons:</h2>
|
||
<ul>
|
||
<li>2g/L Mosaic (Hop Stand&nbsp;40mn)</li>
|
||
<li>2g/L Citra (Hop Stand&nbsp;40mn)</li>
|
||
<li>4g/L Citra à cru (en deux&nbsp;fois)</li>
|
||
<li>4g/L Mosaic à cru (en deux&nbsp;fois)</li>
|
||
</ul>
|
||
<h2 id="eau">Eau:</h2>
|
||
<ul>
|
||
<li>Utilisation d&#8217;eau de source, pour pouvoir corriger les sulfates /&nbsp;chlorures.</li>
|
||
<li>200 Chlorures pour 100&nbsp;Sulfates.</li>
|
||
<li>
|
||
<h2 id="gypse-1g">Gypse:&nbsp;1g</h2>
|
||
<dl>
|
||
<dd>1.8g&nbsp;(=4.05ml)</dd>
|
||
</dl>
|
||
</li>
|
||
<li>Acide lactique:&nbsp;0.4ml</li>
|
||
</ul>
|
||
<h2 id="profil-dempatage">Profil&nbsp;d&#8217;empatage:</h2>
|
||
<ul>
|
||
<li>68°C durant&nbsp;40mn;</li>
|
||
<li>75°C durant 10mn&nbsp;(mash-out)</li>
|
||
</ul>
|
||
<h2 id="levure">Levure</h2>
|
||
<ul>
|
||
<li>GigaYeast «Vermont Ale». Le nombre de cellules n&#8217;est pas indiqué sur le packaging, ni en&nbsp;ligne.</li>
|
||
</ul>
|
||
<h1 id="deroule">Déroulé</h1>
|
||
<ul>
|
||
<li>12h50: empâtage à&nbsp;68°C</li>
|
||
<li>pH = 5.5. Ajout de 0.2&nbsp;d&#8217;acide.</li>
|
||
<li>Pas mal de mesures du pH:<ul>
|
||
<li>5.2@23°C&nbsp;(13h05)</li>
|
||
<li>5.4@18°C&nbsp;(13h05)</li>
|
||
<li>5.2@27°C&nbsp;(13h15)</li>
|
||
<li>5.3@19°C&nbsp;(13h20)</li>
|
||
<li>5.4@25°C&nbsp;(13h30)</li>
|
||
</ul>
|
||
</li>
|
||
<li>13h33: Mash-out à 78°C durant&nbsp;10mn</li>
|
||
<li>Test à l&#8217;iode: <span class="caps">OK</span></li>
|
||
<li>14h11: 1er rincage. Densité premier mout:&nbsp;1070</li>
|
||
<li>15h40: Hop Stand (15g Citra / 15g&nbsp;Mosaic)</li>
|
||
</ul>
|
||
<h1 id="fermentation">Fermentation</h1>
|
||
<ul>
|
||
<li>31/12/2017 - Fermentation à&nbsp;20°C</li>
|
||
<li>01/01/2018 - Ajout de 12g de Citra et 12g de Mosaic après deux&nbsp;jours.</li>
|
||
<li>10/01/2018 - 1.040 <span class="caps">SG</span> = 1.008&nbsp;corrigé</li>
|
||
<li>15/01/2018 - Ajout de 12g de Citra et 12g de&nbsp;Mosaic</li>
|
||
<li>15/01/2018 - Cold&nbsp;Crash</li>
|
||
<li>21/01/2018 - Mise en bouteille. Resucrage à&nbsp;7g/L.</li>
|
||
</ul>
|
||
<h1 id="observations">Observations:</h1>
|
||
<ul>
|
||
<li>En mettant 1.5ml d&#8217;acide, si on mesure le pH de l&#8217;eau, il est à 3.5. Ça nous à pas mal effrayé, puisque on a pas trop l&#8217;habitude de monitorer le pH. On refait: 0.4ml d&#8217;acide = pH de 4.1. Au final, cela ne semble pas utile de mesurer le pH de l&#8217;eau avant de mettre son&nbsp;grain.</li>
|
||
<li>Je le savais déjà, mais travailler à deux en discutant n&#8217;est pas vraiment une bonne idée: sur les opérations un peu technique, un manque de concentration se fait tout de suite&nbsp;ressentir.</li>
|
||
<li>BeerSmith semble proposer un outil pour calculer les modifications de pH, je devrais l&#8217;utiliser la prochaine&nbsp;fois.</li>
|
||
<li>Baisser le ration d&#8217;empâtage: On s&#8217;est retrouvé avec beaucoup trop d&#8217;eau de rincage, alors qu&#8217;on était sur une bière assez faible en&nbsp;densité.</li>
|
||
<li>Au final, ajouter l&#8217;acide au départ est problématique pour le pH de l&#8217;eau qui baisse énormement. Après quelques recherches, il semble qu&#8217;il faille faire confiance au logiciel, et prendre une seule mesure de pH à 10mn (cela devrait être stable). Le pHmetre est aussi peut-être en&nbsp;cause.</li>
|
||
<li>D&#8217;une manière générale, j&#8217;ai l&#8217;impression d&#8217;être un peu à l&#8217;arrache sur la partie fermentation. Il faudrait vraiment que j&#8217;ai un plan et que je m&#8217;y tienne. Plusieurs questions me semblent encore à résoudre: combien de temps laisser le houblon à cru ? A quelle température&nbsp;?</li>
|
||
</ul></content><category term="notes"></category></entry><entry><title>NEIPA #2</title><link href="https://blog.notmyidea.org/neipa-2.html" rel="alternate"></link><published>2017-12-18T00:00:00+01:00</published><updated>2017-12-18T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2017-12-18:/neipa-2.html</id><summary type="html"><p><em>Voici quelques prises durant un de mes brassins. L&#8217;idée est de pouvoir les relire et m&#8217;améliorer au fur et à&nbsp;mesure.</em></p>
|
||
<h1 id="objectifs">Objectifs</h1>
|
||
<ul>
|
||
<li>Corriger les erreurs du précédent&nbsp;brassin.</li>
|
||
<li>Éviter les soucis de&nbsp;filtration</li>
|
||
<li>Mieux corriger le&nbsp;pH</li>
|
||
<li>Faire un whirlpool digne de ce nom / avoir moins de trub …</li></ul></summary><content type="html"><p><em>Voici quelques prises durant un de mes brassins. L&#8217;idée est de pouvoir les relire et m&#8217;améliorer au fur et à&nbsp;mesure.</em></p>
|
||
<h1 id="objectifs">Objectifs</h1>
|
||
<ul>
|
||
<li>Corriger les erreurs du précédent&nbsp;brassin.</li>
|
||
<li>Éviter les soucis de&nbsp;filtration</li>
|
||
<li>Mieux corriger le&nbsp;pH</li>
|
||
<li>Faire un whirlpool digne de ce nom / avoir moins de trub dans le&nbsp;fermenteur</li>
|
||
<li>Ne pas se laisser avoir par la baisse de température durant&nbsp;l&#8217;empâtage.</li>
|
||
</ul>
|
||
<h1 id="recette">Recette</h1>
|
||
<p><span class="caps">DI</span>: 1060 (1050 mesuré)
|
||
pH: 5.2&nbsp;(atteint)</p>
|
||
<h2 id="grains">Grains</h2>
|
||
<ul>
|
||
<li>90%&nbsp;Pils</li>
|
||
<li>10% Flocons&nbsp;d&#8217;avoine</li>
|
||
</ul>
|
||
<h2 id="houblons">Houblons</h2>
|
||
<ul>
|
||
<li>2g/L Wakatu (au&nbsp;Whirlpool)</li>
|
||
<li>2g/L Motueka (au&nbsp;Whirlpool)</li>
|
||
<li>4.5g/L Wakatu à cru (en deux&nbsp;fois)</li>
|
||
<li>2.5g/L Motueka à cru (en deux&nbsp;fois)</li>
|
||
</ul>
|
||
<h2 id="eau">Eau</h2>
|
||
<ul>
|
||
<li>Utilisation d&#8217;eau de source, pour pouvoir corriger les sulfates /&nbsp;chlorures.</li>
|
||
<li>200 Chlorures pour 100&nbsp;Sulfates.</li>
|
||
<li>Gypse:&nbsp;0.9g</li>
|
||
<li>CaCl2:&nbsp;3.4g</li>
|
||
<li>Acide lactique: Au batch précédent, j&#8217;avais mesuré 5.6, donc: ajout de +2ml d&#8217;acide&nbsp;(=2.4g).</li>
|
||
<li>Utilisation d&#8217;Irish Moss (2g) pour coaguler les&nbsp;protéines.</li>
|
||
</ul>
|
||
<h2 id="profil-dempatage">Profil&nbsp;d&#8217;empatage</h2>
|
||
<ul>
|
||
<li>65°C durant 90mn (68°C au départ, 65&nbsp;visé)</li>
|
||
<li>78°C durant 10mn&nbsp;(mash-out)</li>
|
||
</ul>
|
||
<h2 id="levure">Levure</h2>
|
||
<ul>
|
||
<li>London Ale <span class="caps">III</span>.</li>
|
||
</ul>
|
||
<h1 id="deroule">Déroulé</h1>
|
||
<ul>
|
||
<li>18h36 - empatage à&nbsp;65°C</li>
|
||
<li>19h16- pH =&nbsp;5.2</li>
|
||
<li>Densité 1er moût:&nbsp;1070</li>
|
||
<li>Ébullition importante pour atteindre 6,2L avec la bonne&nbsp;densité.</li>
|
||
<li>Mash-out à 78°C durant&nbsp;10mn</li>
|
||
<li>Test à l&#8217;iode: <span class="caps">NOK</span></li>
|
||
<li>1er rincage. Densité premier mout:&nbsp;1070</li>
|
||
<li>15h40: Hop Stand (15g Citra / 15g&nbsp;Mosaic)</li>
|
||
</ul>
|
||
<h1 id="fermentation">Fermentation</h1>
|
||
<ul>
|
||
<li>18/12/2017 - Fermentation à&nbsp;18°C</li>
|
||
<li>21/12/2017 - Ajout de 13.5g de Wakatu et 7.5g de&nbsp;Motueka</li>
|
||
<li>30/12/2017 - Ajout de 13.5g de Wakatu et 7.5g de&nbsp;Motueka</li>
|
||
<li>30/12/2017 - Passage à&nbsp;10°C.</li>
|
||
<li>15/01/2018 - Cold&nbsp;Crash</li>
|
||
<li>21/01/2018 - Mise en bouteille. Resucrage à&nbsp;7g/L.</li>
|
||
</ul>
|
||
<h1 id="observations">Observations:</h1>
|
||
<ul>
|
||
<li>Je change de technique, et mets l&#8217;acide lactique directement dans&nbsp;l&#8217;eau.</li>
|
||
<li>Je concasse moins fin mais reteste quand même l&#8217;avoine. Aucun souci de filtration (mais l&#8217;avoine n&#8217;est pas&nbsp;concassé).</li>
|
||
<li>1g de CaCl2 ~= 2.25ml en solution à&nbsp;33%.</li>
|
||
<li>Les deux thermomètres n&#8217;affichent pas la même température. Super&nbsp;:(.</li>
|
||
<li>Au final, j’empâte dans une casserole pour pouvoir faire un&nbsp;mash-out.</li>
|
||
<li>Le pH oscille pas mal durant l&#8217;empâtage. J&#8217;ai mesuré des pH de 4.9 à certains moments, mais au final la dernière lecture est de 5.2, ce qui me semble&nbsp;bon.</li>
|
||
<li>Le système que j&#8217;utilise (refroidisseur en cuivre) pour refroidir mon moût n&#8217;est pas génial parce que ça mélange pas mal ce qu&#8217;on veut voir se déposer au fond de la cuve. Refroidir directement dans l&#8217;évier est vachement plus simple (c&#8217;est pratique de faire du 6L pour çà&nbsp;!)</li>
|
||
<li>Le teste à l&#8217;iode était positif: tout n&#8217;était pas converti. Mais à 90mn de mash, je ne crois pas pouvoir faire grand chose de&nbsp;plus.</li>
|
||
<li>Idée en vrac, à voir à la dégustation, mais ajouter un peu de cara pourrait être&nbsp;sympa.</li>
|
||
<li>L&#8217;irish moss à vraiment bien fonctionné. Je me demande si je ne devrais pas même laisser décanter un peu plus longtemps durant le whirlpool pour avoir un effet encore plus&nbsp;impressionnant.</li>
|
||
<li>Je trouve que l&#8217;efficacité de cette brasserie est vraiment&nbsp;pourrie.</li>
|
||
<li>Un peu d&#8217;eau est venue diluer le moût (<span class="caps">DI</span> = 1050 au lieu de 1060&nbsp;souhaité)</li>
|
||
<li>Au goût, le moût à vraiment un goût qui m&#8217;assèche la gorge. Trop de modifications de l&#8217;eau ? A voir si l&#8217;effet persiste après&nbsp;fermentation.</li>
|
||
<li>A priori, d&#8217;après un article de Scott Janish, empâter avec de l&#8217;avoine cru ne fonctionne que si on empate haut. Ca à un impact sur l&#8217;efficacité générale (2h pour conversion totale, c&#8217;est peut-être pour ça que mon teste à l&#8217;iode était&nbsp;positif)</li>
|
||
<li>Sur l&#8217;avoine toujours, il faut <strong>dépasser 18%</strong> pour avoir un côté moelleux. Certains mettent jusqu&#8217;à 40%&nbsp;!</li>
|
||
</ul></content><category term="notes"></category></entry><entry><title>L’arrivée du trouble (ou comment faire des NEIPA ?)</title><link href="https://blog.notmyidea.org/larrivee-du-trouble-ou-comment-faire-des-neipa.html" rel="alternate"></link><published>2017-10-17T00:00:00+02:00</published><updated>2017-10-17T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2017-10-17:/larrivee-du-trouble-ou-comment-faire-des-neipa.html</id><summary type="html"><p><strong>Ceci est une traduction d&#8217;un article paru dans le magazine « Brew Your Own » en Octobre 2016, écrit par Dave&nbsp;Green</strong></p>
|
||
<p>C&#8217;est la saison des élections aux états unis et la bataille entre les partis politiques semble être plus controversée que d&#8217;habitude. Coincidemment, les buveurs de bières « Craft …</p></summary><content type="html"><p><strong>Ceci est une traduction d&#8217;un article paru dans le magazine « Brew Your Own » en Octobre 2016, écrit par Dave&nbsp;Green</strong></p>
|
||
<p>C&#8217;est la saison des élections aux états unis et la bataille entre les partis politiques semble être plus controversée que d&#8217;habitude. Coincidemment, les buveurs de bières « Craft» <span class="caps">US</span> semblent avoir leur propre bataille qui divise au moins autant: une <span class="caps">IPA</span> peut elle être aussi trouble qu&#8217;une hefeweizen ? En provenance du coin Nord Est des États-Unis, l&#8217;<span class="caps">IPA</span> trouble est en passe de devenir culte depuis quelques années. Mais la mode ne vient pas sans contrecoup. En fait, tout le monde y va de son opinion chez les brasseurs artisanaux. Pour ceux qui apprécient ce type d&#8217;<span class="caps">IPA</span>, l&#8217;apparence trouble signifie que les gorgées qui suivent seront extrèmenent riches en huiles de houblons; pour les autres, l&#8217;apparence est un affront à des principes ancestraux. Que vous les appeliez des rince-bouches, des soupes boueuses, brillantes ou horribles, ne vous faites pas de fausse idée: ces ales troubles sont là pour&nbsp;rester.</p>
|
||
<p>Pour commencer cette histoire, revenons un peu au début des années 1990. La scène brassicole artisanale était en train de vivre son premier boom et les nouvelles brasseries faisaient leur apparition dans tous les coins des États-Unis. Menée par Sierra Nevada Brewing Company, les American Pale Ale et les American <span class="caps">IPA</span> étaient en train d’émerger en tant que styles populaires parmi les amateurs de bière, pour leurs caractéristiques riches en&nbsp;houblon.</p>
|
||
<p>Le niveau d&#8217;amertume était un trait notoire, et avoir la bonne morsure d&#8217;amertume était essentiel pour une <span class="caps">IPA</span>. L&#8217;innovation a ensuite commencée à arriver sur la cote Ouest des États Unis à la fin des années 1990, et au début des années 2000, quand quelques doubles ou impériales <span class="caps">IPA</span> telles que Pliny the Elder de Russian River et Ruination <span class="caps">IPA</span> de Stone Brewing ont commencées à sortir des fermenteurs. Alors que celles ci contenaient énormement de « morsure du houblon», ce qui séparaient ces bières de beaucoup d&#8217;autres versions du style était le fait que le nez et la saveur du houblon semblaient éclater de la&nbsp;bière.</p>
|
||
<p>Du point de vue du brasseur, les huiles essentielles de ces houblons étaient bien plus présents que les acides alpha. En utilisant un profil de malt neutre et une souche de levure neutre, ces bières laissaient la part belle aux houblons. Ces brasseurs utilisaient aussi des houblons souvent critiqués, forts en acides alpha, tels que Columbus, Centennial, Simcoe et Chinook à la fin de l&#8217;ébullition ou en houblonnage à cru&#8230; et en grosses quantitées. Cela peut sembler comme une pratique courante pour une <span class="caps">IPA</span> actuellement, mais il y a à peine 15 ans, la plupart de la littérature évitaient d&#8217;utiliser ces variétés de houblon pour une utilisation autre que de l&#8217;amérisant. Lévolution d&#8217;une nouvelle American <span class="caps">IPA</span> était en train de prendre forme, sur la cote Ouest des étants unis, un style que les buveurs de bière ont nommé la « West Coast <span class="caps">IPA</span>».</p>
|
||
<h1 id="la-phase-de-demarrage">La phase de&nbsp;démarrage</h1>
|
||
<p>De retour sur la cote Est des États-Unis, dans un petit brewpub de Burlington à Vermont, deux brasseurs commencent innocemment à développer un type d&#8217;American <span class="caps">IPA</span> avec des objectifs similaires que les brasseurs de la côte Ouest, mais en utilisant une stratégie différente. Crée en 1988 par Greg Noonan et Steve Polewacyk, le « Vermont Pub <span class="amp">&amp;</span> Brewery » deviendra le berceau d&#8217;une nouvelle révolution autour des <span class="caps">IPA</span>.</p>
|
||
<p>Souvent citée comme étant les premiers brasseurs des Black <span class="caps">IPA</span> modernes ainsi que des New England <span class="caps">IPA</span>, offrant une variété de bières qui était extrèmement rare à cette époque, le « Vermont Pub <span class="amp">&amp;</span> Brewery » a des racines provenant de la connaissance du brassage et de la chimie de Greg Noonan, ainsi que son flair pour la&nbsp;créativité.</p>
|
||
<p>Se reposant sur la révolution de la bière mondiale (menée par Michael Jackson), Greg Noonan à exploré des styles de bières qui étaient en dehors des sentiers battus, même pour les brasseurs qui étaient déjà en avance sur leur&nbsp;temps.</p>
|
||
<p>Arrive John Kimmich, qui, en 1994 à déménagé dans le Vermont avec l&#8217;objectif de brasser sous la tutelle de Greg Noonan. John à travaillé un temps à Pittsburg (en Pennsylvanie) dans un <em>home brewshop</em> nommé Country Wines. Il a travaillé avec Alexis Hartung et sa grande bibliothèque sur le brassage maison et a eu son premier éclair de génie brassicole en lisant le livre de Greg Noonan « New Brewing Lager Beer ». Un an plus tard, il commence à travailler au « Vermont Pub <span class="amp">&amp;</span> Brewery ». En quelques mois, Greg commence à avoir confiance dans les capacités de son nouveau protégé. Avec chaque bière que John travaillait, le mentor était impressionné. Après douze mois, Greg donne la liberté à John d’expérimenter seul sur les&nbsp;recettes.</p>
|
||
<p>En 1997, John part du « Vermont Pub <span class="amp">&amp;</span> Brewery » et cofonde avec sa femme Jen un brewpub en 2003, le « Alchemist Pub <span class="amp">&amp;</span> Brewery », situé 30mn à l&#8217;est de Burlington à Waterbury dans le Vermont. A cette époque, Waterbury était un petit village dormant du New England, n&#8217;attirant pas grand monde autre que quelques touristes. Il était par contre assez bien situé, à un croisement des chemins, juste à la sortie d&#8217;une autoroute majeure, Waterbury est facilement accessible par à la fois les voyageurs en route pour les endroits touristiques et pour les locaux en allant / revenant du travail ou pour leurs excursions shopping. Grâce à ces quelques éléments, Waterbury s&#8217;est donc révélé êre un excellent spot pour Jen et&nbsp;John.</p>
|
||
<p>Une caractéristique unique des bières houblonnées de Kimmich était que lorsque servies fraîches et non filtrées, elles étaient souvent assez troubles. Il trouvait que filtrer ses bières pouvait introduire de l&#8217;oxygène non souhaité, enlevant de la bière beaucoup d&#8217;aspects intéressants. Il utilisait une souche nommée Conan (<span class="caps">VPB1188</span>), une levure que son mentor a développé et que maintenant beaucoup connaissent. Avec les dérivés Anglais, la souche de levure Conan, les bonnes connaissances en brassage de John, ainsi que son habitude à expérimenter avec les houblons, on se retrouve avec une combinaison gagnante pour une révolution du brassage sur la côte&nbsp;est.</p>
|
||
<h1 id="la-phase-de-croissance">La phase de&nbsp;croissance</h1>
|
||
<p>En 2007, alors que j&#8217;allais au festival des brasseurs du Vermont, la queue pour accéder au stand de The Alchemist était d&#8217;au moins 20 minutes pour un verre. Certaines personnes remplissaient leurs verres et retournaient faire la queue pour avoir la chance de goûter une autre de ces bières tant acclamées, en particulier pour Heady Topper. Pour la première fois brassée en 2003, Heady Toper retenait alors l&#8217;attention, alors qu&#8217;elle n&#8217;était réellement qu&#8217;une parmi les nombreuses <span class="caps">IPA</span> acclamées de chez The Alchemist. Des histoires circulaient comme quoi certaines personnes amenaient leurs pintes aux toilettes pour remplir des bouteilles, les capsuler et les ramener chez eux, puisque le bar ne proposait pas de remplir de Growlers à l&#8217;époque, ni ne vendait de bouteilles. Je pensais alors que l&#8217;engouement pour ces IPAs avait atteint une sorte de paroxysme. Je n&#8217;avais pas encore compris que le feu était seulement en train de se&nbsp;construire.</p>
|
||
<p>J&#8217;ai récemment demandé à Shaun Hill, de la brasserie « Hill Farmsted » à Greensborrow Bend dans le Vermont, classée « meilleure brasserie du monde » 3 des 4 dernières années sur RateBeer.com, quel était sa relation avec John Kimmich à l&#8217;époque. Shaun brassait à l&#8217;époque 30mn plus loin, à Stowe, dans un brewpub appelé « The&nbsp;Shed».</p>
|
||
<p>« En 2005, je ne tarissais pas d&#8217;éolges pour les bières de John me faisait le plaisir de critiquer mes bières » me dit Hill, « Cette relation à évoluée avec le temps, plus specialement lorsque j&#8217;ai déménagé au Danemark et que cette conversation est devenue une conversation entre pairs, poussant l&#8217;autre dans de nouvelles directions.». Avec le decès de Greg Noonan en 2009, l&#8217;ancien protégé est devenu le nouveau mentor. Lors d&#8217;un échange avec Joel Mahaffey de Foundation brewing Co, à Portland à propos des IPAs influentes pour cette nouvelle révolution, il dit de The Alchemist « Quiconque réponds à cette question et oublie Heady Topper, ils sont à coté de la plaque. Il s&#8217;agit de la première <span class="caps">IPA</span> trouble, et à laissée une marque sur la communauté&nbsp;brassicole.»</p>
|
||
<p>Ce qui à emergé dans le coin nord-est des états unis est une explosion de nouvelles brasseries produisant des Pale Ale, des <span class="caps">IPA</span> et des double <span class="caps">IPA</span> basées sur la non filtration, l&#8217;explosion de saveurs, et un corps doux, un style que Greg Noonan et John Kimmich ont découvert, et qu&#8217;ensuite Shaun Hill à continué à affiner. John et Shaun ont séparemment pointé du doigt le fait qu&#8217;ils brassaient juste des bières à leur convenance, et qu&#8217;ils appréciaient le produit fini. Le terme « Juicy <span class="caps">IPA</span> » s&#8217;est retrouvé être un nom pour ces bières, et la texture est souvent aussi importante que le nez et le gout de houblons. Et comme les <span class="caps">IPA</span> de la côte Ouest se sont répendues en 2008, les bières troubles, non filtrées, les New England <span class="caps">IPA</span> se répendent en&nbsp;2016.</p>
|
||
<h1 id="cest-parti">C&#8217;est parti&nbsp;!</h1>
|
||
<p>Il est maintenant temps de passer à la brasserie et de regarder comment faire pour brasser une <span class="caps">IPA</span>, New England style. Shaun Hill dit « soyez vous mêmeet faites une bière qui goute, sent et ressemble à ce que vous voulez qu&#8217;elle soit », <span class="caps">JC</span> Tetreault de Trillum à Boston dans le Massachussetts ajoute « la réponse courte… tout est important ! Vous devez vous concentrer sur chaque aspect pour arriver à la bière que vous souhaitez. » L&#8217;objectif est d&#8217;arriver à une bière douce, un peu ronde, presque tropicale, à la texture ressemblant presque à un jus de fruit, laissant une morsure subtile sur la langue en fin de bouche graçe au&nbsp;houblon.</p>
|
||
<h2 id="les-malts">Les&nbsp;malts</h2>
|
||
<p>Tout comme les IPAs de la cote Ouest, les <span class="caps">NEIPA</span> sont relativement simples en malts. Le style évite les malts qui ajoutent des saveurs de pain et de crackers. Les malts cristals et autres malts au dessus de 20°L (ndt: 52 <span class="caps">EBC</span>) sont d&#8217;une manière générale évités. Ces bières peuvent bénéficier de certains ajouts de malts cristal clairs, mais gardez les à l’œil. Des flocons d&#8217;avoine, d&#8217;orge, de blé et autres peuvent être ajoutés pour contribuer au corps, mais ne pensez pas qu&#8217;ils soient une necessité. J&#8217;ai pu jouer avec des pourcentages de 15% de flocons dans mes recettes, et les résultats étaient presque excessifs. <span class="caps">JC</span> Tetreault dit que « à propos des ajouts de céréales non maltés et de flocons… nous ne les utilisons pas dans toutes nos bières basées sur le houblon. En fait, une proportion plutôt petite de nos bières basées sur le houblon en font usage». Les ajouts de sucre tels que les dextrose, saccharose et sucres crus augmentent la densité du moût pour s&#8217;assurer de la sécheresse dans les versions plus alcoolisées. Si vous choisissez d&#8217;ajouter du sucre cru, encore une fois, faites en sorte que l&#8217;ajout soit modeste; j&#8217;ai trouvé que certaines saveurs de mélasses avaient tendance à arriver à partir de 10% du total du grain. L&#8217;objectif est de garder les houblons comme caractéristique principale de la bière, tout en ayant une base de malt douce mais&nbsp;présente.</p>
|
||
<h2 id="les-levures">Les&nbsp;levures</h2>
|
||
<p>Et c&#8217;est ici que les <span class="caps">NEIPA</span> dérivent des <span class="caps">IPA</span> de la cote Ouest. L&#8217;ajout des levures ainsi que le traitement à partir de la fermentation semble être la plus grosse différence entre les deux styles. D&#8217;abord, regardons comment ces bières sont fermentées. La plupart des <span class="caps">NEIPA</span> ne sont pas clarifiées dans le fermenteur avec des agents clarifiant tels que de la gélatine, du Biofine® ou du Polyclar™, et elles ne sont pas filtrées ou centrifugées plus tard pour clarifier la bière. La pensée derrière ce process est qu&#8217;enlever les levures de la bière à également pour effet d&#8217;enlever les huiles essentielles ainsi que d&#8217;autres nuances subtiles qui permettent à la bière d&#8217;avoir son caractère propre. Cela permet de garder un niveau d&#8217;huiles assez elevé dans le produit fini. Deuxièmement, les brasseurs de New England fermentent en utilisant une souche de levure d&#8217;origine anglaise. Ashton Lewis, l&#8217;éditeur technique de Brew Your Own précise « D&#8217;après des études <span class="caps">ADN</span>, la levure California Ale (White Labs <span class="caps">WLP001</span>, Wyeast 1056 et les autres souches de Chico) viendraient plutôt de Cologne, en Allemagne ». Ces souches américaines ont été choisies pour leur capacité à produire des bières claires, transparentes et amères sans ajouter de caractère. Les souches de levure utilisées par les brasseurs de New England <span class="caps">IPA</span> sont utilisées pour ajouter des esters, qui aident à produire le profil juteux de ces bières. Les IPAs brassées avec ces souches ne semblent pas être aussi transparentes que les souches Americaines lorsqu&#8217;elles sont exposées à des niveaux d&#8217;huiles elevés. Ceci vient en désaccord avec la plupart de la littérature sur les souches Anglaises. Si vous lisez la description de la plupart des souches de levures utilisées pour produire ces <span class="caps">IPA</span> troubles, la plupart sont considéeées « hautement floculantes », alors que la souche Chico, souvent utilisée pour les <span class="caps">IPA</span> de la cote Ouest annonce plutôt une floculation moyenne à faible. Pourquoi alors ces bières ne se clarifient pas lorsqu&#8217;elles sont sujettes à des hautes doses de houblon en fin d&#8217;ébullition ou en houblonnage à cru ? Cela reste encore une zone floue, j&#8217;ai donc demandé à quelques personnes dans l&#8217;industrie à propos de ce flou. Certains brasseurs pointent du doigt le fait que ces souches de levures floculent trop rapidement. Cela ne laisse pas le temps aux polyphénols de s&#8217;attacher aux levures, laissant ces composés ainsi que d&#8217;autres composés dérivés du houblon dans la solution plutôt que des les en enlever. Ashton Lewis nous rappelle aussi que le trouble trouvé dans les hefeweizen est principalement causé par les interactions entre les protéines et les polyphénols, et non pas par les&nbsp;levures.</p>
|
||
<p>Donc, quelles sont les souches de levure que vous devriez utiliser ? Le choix est en fait assez large, pour ceux qui souhaitent brasser ces types de American <span class="caps">IPA</span>, referez vous donc aux suggestions données dans les recettes jointes pour quelques&nbsp;idées.</p>
|
||
<h2 id="leau">L&#8217;eau</h2>
|
||
<p>L&#8217;eau joue un rôle prépondérant dans le développement des New England <span class="caps">IPA</span>. Concentrez vous sur les niveaux de dureté de votre eau. Si vous avez une eau assez douce, alors vous avez un bon point de départ. Si vous avez une eau plutôt dure, obtenez un relevé d&#8217;eau (ndt: allez faire un tour sur le site « Eau du bassin Rennais » !). Si vous n&#8217;avez pas ces relevés d&#8217;eau, vous pouvez aussi faire analyser votre eau par des laboratoires, ou vous pouvez le faire vous même grâce à des kits de test de l&#8217;eau. Peu importe ce que vous choisissez, utiliser de l&#8217;eau distillée ou osmosée peut vous fournir une bonne base pour construire le profil d&#8217;eau que vous souhaitez obtenir. Essayez de garder votre niveau de bicarbonate en dessous de 50 <span class="caps">PPM</span> pour votre eau d’empâtage et votre eau de&nbsp;rinçage.</p>
|
||
<p>La prochaine chose sur laquelle se concentrer est vos sulfates et vos chlorures. Ceci est parfois controversé, mais encore une fois peut potentiellement être un facteur différenciant entre les <span class="caps">IPA</span> de la côte Est et les <span class="caps">IPA</span> de la côte Ouest. Quand j&#8217;ai commencé à jouer avec la composition de mon eau, j&#8217;ai traité l&#8217;eau de mes <span class="caps">IPA</span> pour atteindre un rapport 2:1 de sulfates / chlorures, ce qui s&#8217;est traduit par 100:50 <span class="caps">PPM</span>. J&#8217;ai produit plusieurs bières qui pouvaient rivaliser (selon moi) avec certaines que mes idoles produisaient. Mais, dans l&#8217;esprit du brassage amateur, j&#8217;ai continué à expérimenter. J&#8217;ai changé l&#8217;équilibre de sulfate / chlorures à 200:<span class="caps">50PPM</span> sans que je perçoive un changement. J&#8217;ai ensuite essayé 100:100 et trouvé que ça me plaisait un peu plus. Mes trouvailles ne sont pas la seule preuve anecdotique que booster le niveau de chlorures peut bénéficier à ce style de bières. Si vous cherchez à ajuster vos sulfates et for chlorures pour votre eau d&#8217;empâtage et de rincage, je vous encourage à jeter un oeil à l&#8217;article de Scott Janish du 7 Mars 2016 intitulé « Mouthfeel softness ». Scott y parle des effets négatifs d&#8217;un taux de sulfates elevé et des aspects positifs d&#8217;un niveau de chlorures&nbsp;elevé.</p>
|
||
<h2 id="les-houblons">Les&nbsp;houblons</h2>
|
||
<p>Généralement, l&#8217;amertume des houblons dans ce type d&#8217;<span class="caps">IPA</span> joue un rôle support, qui vient équilibrer le corps et la douceur des malts. Premièrement, gardez l&#8217;ajout de houblons amérisants modéré à faible. Vous pouvez expérimenter avec l&#8217;ajout de houblons amérisants mais je n&#8217;ai jamais eu l&#8217;occasion de trouver qu&#8217;une utilisation importante de houblons amérisants menait à une meilleure New-England <span class="caps">IPA</span>. Utilisez des houblons hauts en alpha tels que Magnum, Warrior™ ou Bravo si vous choisissez d&#8217;utiliser des houblons en cône ou en pellets, et je recommande de garder les ajouts d&#8217;amérisants assez faibles. D&#8217;habitude, j&#8217;essaye houblonner pour un rapport de 1:3 <span class="caps">BU</span>:<span class="caps">GU</span> (amertume sur densité). Cela signifie que quand je vise une densité cible de 1.066, l&#8217;ajout de houblons à 60mn est de 22 IBUs. Cela est fait pour éviter d&#8217;ajouter une dureté qui peut provenir d&#8217;une ébullition d&#8217;une quantité plus elevée de houblons. L&#8217;autre option est d&#8217;utiliser des extraits de houblon, qui peuvent contribuer les acides alpha nécessaires pour obtenir la bonne amertume, sans ajouter de polyphénols, que certains brasseurs pensent être à l&#8217;origine d&#8217;une certaine&nbsp;dureté.</p>
|
||
<p>Les ajouts de houblons en fin d&#8217;ébullition jouent un rôle beaucoup plus important pour la production de New-England <span class="caps">IPA</span>. Des apports copieux à la fin de l&#8217;ébullition ou au <em>flame-out</em> sont utiles pour tout type d&#8217;<span class="caps">IPA</span> hautement aromatique. Cela ajoutera des IBUs pour compléter votre apport en houblons amérisants et commencera à créer votre profil d&#8217;huiles. Je trouve que des variétés plus mordantes / piquantes comme le Simcoe®, Columbus, Chinook et Apollo fonctionnent bien à cette étape. Chaque brasseur semble trouver sa technique ici, qu&#8217;il s&#8217;agisse de faire plusieurs ajouts à 20mn ou moins puis de baisser à une température précise pour faire un <em>hop stand</em>, ou bien de simplement ajouter tous les houblons au <em>flame-out</em> et de les laisser durant 20 minutes ou plus. Il ne semble pas qu&#8217;il y ait de mauvaise manière de faire, juste plusieurs manières d&#8217;extraire les huiles essentielles des houblons à une température pas trop&nbsp;haute.</p>
|
||
<p>Le houblonnage à cru est votre prochain objectif. J&#8217;aimerais me concentrer sur les techniques plutôt que sur les quantités ou variétés puisque la technique semble être le plus important ici. Ceci dit, une chose est sure, ne soyez pas trop timide avec les ajouts durant le houblonnage à cru. 7.5g/L est certainement un bon point de départ. Vous pouvez ajuster en fonction de vos résultats. Les brasseurs Scott Janish et Michael Tonsmeir ajoutent que mettre ces bières en fûts à quelques avantages. Houblonner dans le fût, purger au <span class="caps">CO2</span> et le fait de ne pas avoir de période prolongée de carbonatation sont déjà deux des avantages des fûts sur les&nbsp;bouteilles.</p>
|
||
<p>Alors, quand est le meilleur moment pour faire son houblonnage à cru ? Biern que ce ne soit pas une necessité, le fait de faire son houblonnage à cru en deux fois semble être un bon choix pour ce genre d&#8217;<span class="caps">IPA</span>. Prenez ce que vous pensiez ajouter lors du houblonnage à cru et séparez le en deux. Le premier ajout se fera durant la phase active de fermentation alors que le second se fera quand la fermentation se sera calmée et que les levures auront flocculées. Le premier ajout peut se faire à différents stades de la fermentation primaire; certains brasseurs les ajoutent au même moment qu&#8217;ils ensemencent, certains autres lorsque le krausen est haut, alors que la plupart l&#8217;ajoutent vers la fin de la fermentation. Je préfère faire le premier ajout une fois que le krausen est redescendu. Les hétérosides et les bio-transformations sont des éléments importants dans cette discussion à propos de comment la levure intéragit avec les huiles des houblons et les autres dérivés du houblon. Je trouve que les houblons ajoutés à la fin de l&#8217;ébullition vont apporter des caractéristiques similaires que les huiles de houblons ajoutés durant le ébut de la fermentation. Pour ce qui est du second ajout, l&#8217;objectif est d&#8217;attendre que la fermentation se soit calmée. Le timing n&#8217;est pas vraiment un facteur important ici, mais l&#8217;introduction d&#8217;oxygène est un point crutial. Prenez bien soin d&#8217;introduire le moins possible d&#8217;oxygène dans la bière à ce moment&nbsp;çi.</p>
|
||
<p>Dernièrement, quelque chose qui est nouveau pour moi: le houblonnage à cru sous pression. Cela vous demandera de l&#8217;équipement supplémentaire, principalement quelque chose apellée une « Spunding Valve». Il s&#8217;agit d&#8217;une valve qui permet de garder une certaine pression dans le fermenteur. Si la pression dépasse la valeur cible, alors la valve s&#8217;ouvre pour faire redescendre le fermenteur à la valeur souhaité. Mais, en quoi cela pourrait-être interéssant pour nous ? Parce que nous cherchons à garder un maximum de houblons aromatiques, en évitant d&#8217;en perdre. Les brasseurs amateurs ainsi que les brasseurs pros se sont penchés sur la question des spuinding valve de plus en plus dernièrement pour la fermentation primaire et pour le houblonnage à&nbsp;cru.</p>
|
||
<p>La révolution de la côte Est bat son plein et si vous ne pouvez pas venir sur place pour goûter un extrait, vous pouvez maintenant au moins commencer à brasser des bières avec un caractère similaire. Et si vous n&#8217;êtes pas un fan de ce type de bière, faites bien attention à laisser ceux qui apprécient déguster en&nbsp;paix.</p>
|
||
<p>Remerciements spéciaux à tous les brasseurs qui ont contribué à la production de cet article: John Kimmich de The Alchemist, Shaun Hill de Hill Farmstead, Joel Mahaffrey de Foundation Brewing, Matt Nadeau de Rock Art Brewery et <span class="caps">JC</span> Tetrealt de Trillium. Allez leur rendre visite&nbsp;!</p></content><category term="notes"></category></entry><entry><title>Un club des brasseurs amateurs Rennais</title><link href="https://blog.notmyidea.org/un-club-des-brasseurs-amateurs-rennais.html" rel="alternate"></link><published>2017-10-06T00:00:00+02:00</published><updated>2017-10-06T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2017-10-06:/un-club-des-brasseurs-amateurs-rennais.html</id><summary type="html"><p>En Mars dernier, suite à quelques discussions entre brasseurs amateurs, on à décidé de monter <a href="https://framalistes.org/sympa/subscribe/brassam-rennes">une liste de diffusion</a> pour faciliter les échanges autour du brassage amateur sur Rennes et ses&nbsp;alentours.</p>
|
||
<p>Un peu plus tard, <a href="https://www.facebook.com/groups/899071153568179/">un groupe Facebook</a> est venu s&#8217;ajouter, et c&#8217;est vrai qu&#8217;on sent …</p></summary><content type="html"><p>En Mars dernier, suite à quelques discussions entre brasseurs amateurs, on à décidé de monter <a href="https://framalistes.org/sympa/subscribe/brassam-rennes">une liste de diffusion</a> pour faciliter les échanges autour du brassage amateur sur Rennes et ses&nbsp;alentours.</p>
|
||
<p>Un peu plus tard, <a href="https://www.facebook.com/groups/899071153568179/">un groupe Facebook</a> est venu s&#8217;ajouter, et c&#8217;est vrai qu&#8217;on sent une dynamique naissante autour de la brasserie artisanale dans le&nbsp;coin.</p>
|
||
<p>En six mois, on est maintenant une grosse trentaine de personnes à être inscrits sur les listes et à se retrouver de temps à&nbsp;autres.</p>
|
||
<p>On en profite pour s&#8217;échanger des bons plans, déguster nos créations, (essayer de) faire des commandes groupées de malt, et pour se rencontrer pour papoter entre&nbsp;passionnés.</p>
|
||
<p>On a pas mal d&#8217;idées de trucs sympa a faire, entre&nbsp;autres:</p>
|
||
<ul>
|
||
<li>brasser une fois en gros puis se séparer le batch en plein de petits fermenteurs pour essayer différentes levures, différents houblons en <em>dry hop</em>,&nbsp;etc.</li>
|
||
<li>A la dernière rencontre, on s&#8217;est mis d&#8217;accord sur un style de bière pour se lancer un petit défi: tous brasser <a href="https://blog.notmyidea.org/larrivee-du-trouble-ou-comment-faire-des-neipa.html">une <span class="caps">NEIPA</span></a> pour ensuite comparer nos&nbsp;résultats.</li>
|
||
</ul>
|
||
<p>Bref, c&#8217;est plutôt chouette ! Je me suis rendu compte qu&#8217;on avait quasiment aucune existence en dehors des réseaux sociaux, alors je me permet de publier ce petit bout d&#8217;article avec quelques&nbsp;liens…</p>
|
||
<p>Si tu es dans le coin et que tu souhaite nous rencontrer, n&#8217;hésite pas à rejoindre <a href="https://www.facebook.com/groups/899071153568179/">notre groupe de discussion Facebook</a> et notre <a href="https://framalistes.org/sympa/subscribe/brassam-rennes">liste de diffusion mail</a>.</p>
|
||
<p>A bientôt&nbsp;;)</p></content><category term="journal"></category></entry><entry><title>Brasserie du Vieux Singe — Installation en cours.</title><link href="https://blog.notmyidea.org/brasserie-du-vieux-singe-installation-en-cours.html" rel="alternate"></link><published>2017-06-26T00:00:00+02:00</published><updated>2017-06-26T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2017-06-26:/brasserie-du-vieux-singe-installation-en-cours.html</id><summary type="html"><p>Ça fait maintenant quelques mois que j&#8217;ai décidé de <a href="https://www.vieuxsinge.com">changer de métier</a>. Choix à la fois difficile et excitant. Une rupture qui laisse place à quelques étoiles dans les yeux. Enfin, je retrouve l&#8217;envie de créer, et je renoue avec mes rêves, ceux-la mêmes que je croyaient trop …</p></summary><content type="html"><p>Ça fait maintenant quelques mois que j&#8217;ai décidé de <a href="https://www.vieuxsinge.com">changer de métier</a>. Choix à la fois difficile et excitant. Une rupture qui laisse place à quelques étoiles dans les yeux. Enfin, je retrouve l&#8217;envie de créer, et je renoue avec mes rêves, ceux-la mêmes que je croyaient trop fous pour être à portée de&nbsp;main.</p>
|
||
<p>La chose la plus frappante, c&#8217;est la vitesse à laquelle passent les journées: j&#8217;ai <em>vraiment</em> l&#8217;impression d&#8217;avoir quitté Mozilla hier. Si les collègues me
|
||
manquent, je ne ferais machine arrière pour rien au monde: je trouve finalement ce sens qui me manquait&nbsp;cruellement.</p>
|
||
<p>Après quelques hésitations au départ, j&#8217;ai décidé de mettre de côté mes activités liées à l&#8217;informatique: difficile à assumer quand on croise les copin.e.s avec qui on avait l&#8217;habitude de discuter énormement de ces sujets, mais ça permet de laisser plus de place pour l&#8217;humain. Plus de place pour les «Au fait, comment ça va toi ?» quand j&#8217;ai l&#8217;occasion de les recroiser, ce qui n&#8217;est pas plus désagréable&nbsp;:)</p>
|
||
<p>Les journées sont donc organisées autour de la brasserie: beaucoup plus de planification que ce que j&#8217;imaginais au départ. Peut-être que c&#8217;est aussi du au fait que nous soyons tous les deux des ex-informaticiens un peu perfectionnistes sur les bords. On se voit très souvent pour avancer sur des sujets de fond tout comme sur du pratico-pratique. Pour vous donner un ordre d&#8217;idée des questionnements: Quelle taille d&#8217;entreprise ? Quelles valeurs communes ? Quelles bières ? Quelle image donner ? Quelle place donner au confort ? Comment éviter la compétitivité ? Comment réussir à impacter les producteurs (houblon / malt) de manière positive ? Quels salaires se donner&nbsp;?</p>
|
||
<p>Un peu de production quand même (pour les amis) mais on se garde la grosse partie pour le&nbsp;lancement.</p>
|
||
<h2 id="apprentissage">Apprentissage</h2>
|
||
<p>Je profite de ces quelques mois pour apprendre: autour de la fabrication et de la dégustation de bière bien sûr (encore un milieu en constante évolution !), mais pas que. J&#8217;ai maintenant quelques bases de gestion d&#8217;entreprise, en comptabilité, en biologie et en chimie. J&#8217;ai bien dit quelques <em>bases</em>, mais qu&#8217;est-ce que c&#8217;est agréable&nbsp;!</p>
|
||
<p>C&#8217;est assez agréable de se remettre dans une posture d&#8217;apprenant, et d&#8217;avoir le temps pour cet&nbsp;apprentissage.</p>
|
||
<h2 id="questionner-la-posture-de-chef-dentreprise-et-son-rapport-au-temps">Questionner la posture de «Chef d&#8217;entreprise» et son rapport au&nbsp;temps</h2>
|
||
<p>Décider de créer sa boîte, c&#8217;est aussi se poser la question de comment organiser son temps: combien de temps travailler ? Quel temps donner aux loisirs&nbsp;?</p>
|
||
<p>Je trouve rassurant de voir ces interrogations abordées avant-même le démarrage de l&#8217;entreprise. La plupart des personnes qui nous suivent et nous guident partent du postulat qu&#8217;il faudra bosser énormement, là ou nous essayons de trouver un modèle qui soit viable dans le temps, notre souhait est de bosser à 80% (4 jours par&nbsp;semaine).</p>
|
||
<p>Certes, il faut travailler pour que ça tourne, mais il faut aussi s&#8217;accorder des temps de respiration pour être d&#8217;autant plus efficace quand on bosse. C&#8217;est d&#8217;autant plus intéressant de prévoir ces aspects lors de la phase de <em>design</em> de l&#8217;activité: on organise le temps autrement ! Ceux qui me lisent de temps à autre savent que c&#8217;est une constante de mes réflexions, on verra si ça fonctionne dans les&nbsp;faits.</p>
|
||
<h2 id="les-projets-collectifs">Les projets&nbsp;collectifs</h2>
|
||
<p>Un autre point important est la place que le <em>collectif</em> prends dans cette nouvelle expérience. Au départ, quand j&#8217;imaginais le projet sur le court-terme, je mettais la composante collective au second plan dans l&#8217;immédiat (au delà des intéractions avec Fred, mon associé). L&#8217;occasion de travailler à la construction d&#8217;un espace collectif s&#8217;est présentée, et on y travaille&nbsp;actuellement.</p>
|
||
<p>C&#8217;est à la fois riche (en partage de points de vue, en entre-aide) et à la fois difficile (beaucoup d&#8217;heures de réunions, il faut apprendre à communiquer de manière efficace, il faut parfois faire face à des conflits). Dans l&#8217;ensemble, je ne regrette pas ce choix même si il est important de ne pas perdre de vue les objectifs de la brasserie dans&nbsp;l&#8217;histoire.</p>
|
||
<p>Et puis la collaboration ne s&#8217;arrête pas qu&#8217;au collectif d&#8217;activité: le milieu brassicole est en mutation, et les valeurs de partage font bel et bien partie du lot de changements. Les rencontre avec les brasseurs du coin de Rennes le montrent bien: l&#8217;esprit est plus à l&#8217;entraide qu&#8217;à la concurrence, au vu de la demande qui est toujours croissante. Tant mieux, on a autre chose à faire qu&#8217;à se tirer dans les pâtes&nbsp;;)</p>
|
||
<h2 id="besoin-de-concret">Besoin de&nbsp;concret</h2>
|
||
<p>Après cette phase assez énorme de réfléxion, de questionnement, de tricotage, de détricotage, de retricotage, j&#8217;ai bien envie de passer à l&#8217;action; et ça tombe bien, c&#8217;est ce qui est à l&#8217;horizon. L&#8217;idée est d&#8217;ouvrir la brasserie à la fin de cette année pour commencer la commercialisation en Janvier 2018. Ça fait un peu peur de voir l&#8217;échéance arriver, mais c&#8217;est aussi excitant que&nbsp;vertigineux…</p>
|
||
<p>Faire ensemble. Imaginer les choses en petit un peu partout. Collaborer plutôt que se tirer dans les pattes. Renverser la vapeur. Trouver des alliés. Faire levier. Inscrire ses projets dans le temps. C&#8217;est peut-être un peu ça, grandir&nbsp;?</p></content><category term="journal"></category></entry><entry><title>Comment est-ce que vous générez vos formulaires ?</title><link href="https://blog.notmyidea.org/comment-est-ce-que-vous-generez-vos-formulaires.html" rel="alternate"></link><published>2016-05-31T00:00:00+02:00</published><updated>2016-05-31T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-05-31:/comment-est-ce-que-vous-generez-vos-formulaires.html</id><summary type="html"><p><span class="caps">TL</span>; <span class="caps">DR</span>: Je viens à peine de <em>releaser</em> la première version d&#8217;un service de génération de formulaires.
|
||
Allez jeter un coup d&#8217;œil sur <a href="https://www.fourmilieres.net">https://www.fourmilieres.net</a></p>
|
||
<p><em>En février 2012, je parlais ici <a href="https://blog.notmyidea.org/carto-forms.html">d&#8217;un service de génération de formulaires</a>.
|
||
Depuis, pas mal d&#8217;eau à coulé sous …</em></p></summary><content type="html"><p><span class="caps">TL</span>; <span class="caps">DR</span>: Je viens à peine de <em>releaser</em> la première version d&#8217;un service de génération de formulaires.
|
||
Allez jeter un coup d&#8217;œil sur <a href="https://www.fourmilieres.net">https://www.fourmilieres.net</a></p>
|
||
<p><em>En février 2012, je parlais ici <a href="https://blog.notmyidea.org/carto-forms.html">d&#8217;un service de génération de formulaires</a>.
|
||
Depuis, pas mal d&#8217;eau à coulé sous les ponts, on est passé par pas mal d&#8217;étapes pour
|
||
finalement arriver à une première version de ce service de génération de
|
||
formulaires (à la </em>google forms<em>).</em></p>
|
||
<p>En tant qu&#8217;organisateurs d&#8217;évènements (petits et gros), je me retrouve souvent
|
||
dans une situation ou je dois créer des formulaires pour recueillir des
|
||
informations. Actuellement, la meilleure solution disponible est <em>Google Forms</em>,
|
||
mais celle ci à plusieurs problèmes, à commencer par le fait que le code n&#8217;est
|
||
pas libre et que les données sont stockées chez&nbsp;Google.</p>
|
||
<p>La plupart du temps, le besoin est assez simple: je veux spécifier quelques
|
||
questions, et donner un lien à mes amis pour qu&#8217;ils puissent y répondre.
|
||
Je reviens ensuite plus tard pour voir la liste des réponses&nbsp;apportées.</p>
|
||
<p><img alt="Capture de l'interface de création du formulaire" src="https://blog.notmyidea.org/images/formbuilder/formbuilder-build.png"></p>
|
||
<h2 id="fonctionnalites">Fonctionnalités</h2>
|
||
<p>Il existe pas mal de solutions techniques qui essayent de répondre à la même
|
||
problématique, mais la plupart d&#8217;entre elles sont assez souvent compliquées,
|
||
nécessitent de se créer un compte, et/ou ne vous laisse pas la main libre sur
|
||
les données générées, voire le code est assez difficile à faire évoluer ou à&nbsp;déployer.</p>
|
||
<p>Je voulais donc quelque chose de simple à utiliser <em>et</em> pour les créateurs de
|
||
formulaires <em>et</em> pour les utilisateurs finaux. Pas de chichis, juste quelques
|
||
vues, et des URLs à sauvegarder une fois l&#8217;opération&nbsp;terminée.</p>
|
||
<p><img alt="Capture de l'écran avec les URLs générées" src="https://blog.notmyidea.org/images/formbuilder/formbuilder-created.png">
|
||
<img alt="Capture d'écran d'un exemple de formulaire" src="https://blog.notmyidea.org/images/formbuilder/formbuilder-form.png"></p>
|
||
<h3 id="pas-de-compte">Pas de&nbsp;compte</h3>
|
||
<p>Vous n&#8217;avez pas besoin d&#8217;avoir un compte sur le site pour commencer à l&#8217;utiliser.
|
||
Vous créez simplement un nouveau formulaire puis envoyez le lien à vos amis pour
|
||
qu&#8217;eux puissent à leur tour le&nbsp;remplir.</p>
|
||
<p><img alt="Capture de la page d'accueil, ou aucun compte n'est requis" src="https://blog.notmyidea.org/images/formbuilder/formbuilder-welcome.png"></p>
|
||
<h3 id="gardez-la-main-sur-vos-donnees">Gardez la main sur vos&nbsp;données</h3>
|
||
<p>Une fois que vous avez récupéré les réponses à vos questions, vous pouvez
|
||
récupérer les données sur votre machines dans un fichier <code>.csv</code>.</p>
|
||
<p><img alt="Capture de la page de resultats, il est possible de télécharger en CSV." src="https://blog.notmyidea.org/images/formbuilder/formbuilder-results.png"></p>
|
||
<h3 id="api"><span class="caps">API</span></h3>
|
||
<p>L&#8217;ensemble des données sont en fait stockées dans <a href="https://kinto.readthedocs.org">Kinto</a>
|
||
qui est interrogeable très facilement en <span class="caps">HTTP</span>. Ce qui fait qu&#8217;il est très facile de
|
||
réutiliser les formulaires que vous avez construits (ou leurs réponses) depuis
|
||
d&#8217;autres&nbsp;outils.</p>
|
||
<h3 id="auto-hebergeable">Auto-hébergeable</h3>
|
||
<p>Un des objectifs de ce projet est de vous redonner la main sur vos données.
|
||
Bien sur, vous pouvez utiliser l&#8217;instance qui est mise à votre disposition sur
|
||
<a href="https://www.fourmilieres.net">wwww.fourmilieres.net</a>, mais vous pouvez
|
||
également l&#8217;héberger vous même très
|
||
simplement, et vous êtes d&#8217;ailleurs fortement encouragés à le faire ! Notre
|
||
objectif n&#8217;est pas de stocker l&#8217;ensemble des formulaires du monde, mais de
|
||
(re)donner le contrôle aux utilisateurs&nbsp;!</p>
|
||
<h2 id="on-commence-petit">On commence&nbsp;petit…</h2>
|
||
<p>Cette <em>release</em> n&#8217;est (bien sur) pas parfaite, et il reste encore pas mal de
|
||
travail sur cet outil, mais je pense qu&#8217;il s&#8217;agit d&#8217;une base de travail
|
||
intéressante pour un futur où Google n&#8217;a pas la main sur toutes nos&nbsp;données.</p>
|
||
<p>La liste des champs supportés est pour l&#8217;instant assez faible (Texte court,
|
||
Texte long, Oui/Non, choix dans une liste) mais elle à vocation à s&#8217;étendre, en
|
||
fonction des besoins de&nbsp;chacun.</p>
|
||
<p>J&#8217;ai d&#8217;ailleurs créé <a href="https://www.fourmilieres.net/#/form/cfd878264cec4ed2">un formulaire pour que vous puissiez me faire part de vos
|
||
retours</a>, n&#8217;hésitez pas&nbsp;!</p>
|
||
<h2 id="et-euh-comment-ca-marche">Et, euh, comment ça marche&nbsp;?</h2>
|
||
<p>Le <em>formbuilder</em>, comme j&#8217;aime l&#8217;appeler se compose en fin de compte de deux
|
||
parties&nbsp;distinctes:</p>
|
||
<ul>
|
||
<li><a href="https://kinto.readthedocs.org">Kinto</a>, un service qui stocke
|
||
des données coté serveur et qui les expose via des <strong>APIs <span class="caps">HTTP</span></strong></li>
|
||
<li><a href="https://github.com/kinto/formbuilder">Le formbuilder</a>, une application
|
||
JavaScript qui ne tourne que coté client (dans votre navigateur) qui permet
|
||
de construire les formulaires et d&#8217;envoyer les données sur les <em>APIs</em> coté&nbsp;serveur.</li>
|
||
</ul>
|
||
<p>Au niveau de la <em>stack</em> technique, le <strong>formbuilder</strong> est codé en ReactJS. Un
|
||
des points techniques intéressants du projet est qu&#8217;il génère en fin de compte du
|
||
<a href="http://jsonschema.net/"><span class="caps">JSON</span> Schema</a>, un format de validation de données <em><span class="caps">JSON</span></em>.</p>
|
||
<p>Donc, reprenons! Vous arrivez sur la page d&#8217;accueil puis cliquez sur
|
||
&#8220;Create a new form&#8221;, puis vous vous retrouvez face à une interface ou vous pouvez
|
||
ajouter des champs de formulaire. Une fois ce travail effectué, vous appuyez sur
|
||
&#8220;Create the&nbsp;form&#8221;.</p>
|
||
<ul>
|
||
<li>Le <span class="caps">JSON</span> Schema est alors envoyé au serveur Kinto, qui l&#8217;utilisera pour valider
|
||
les données qu&#8217;il recevra par la&nbsp;suite.</li>
|
||
<li>Ce <span class="caps">JSON</span> Schema sera aussi utilisé lors de l&#8217;affichage du formulaire aux
|
||
personnes qui le&nbsp;remplissent.</li>
|
||
<li>Un jeton d&#8217;accès est généré et ajouté à l&#8217;<span class="caps">URL</span>, il s&#8217;agit de l&#8217;identifiant du&nbsp;formulaire.</li>
|
||
<li>Un second jeton d&#8217;accès administrateur et généré, il vous faut le garder de
|
||
coté pour avoir accès aux&nbsp;réponses.</li>
|
||
</ul>
|
||
<p>Bref, en espérant que ça vous serve ! Un petit pas dans la direction des données
|
||
rendues à leurs utilisateurs&nbsp;!</p></content><category term="code"></category></entry><entry><title>Cloisonnement des activités ?</title><link href="https://blog.notmyidea.org/cloisonnement-des-activites.html" rel="alternate"></link><published>2016-05-25T00:00:00+02:00</published><updated>2016-05-25T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-05-25:/cloisonnement-des-activites.html</id><summary type="html"><p>Je vous écris depuis un train, en rentrant de Bordeaux où j&#8217;ai passé quelques
|
||
jours à l&#8217;occasion de <a href="http://sudweb.fr/">SudWeb</a>. Si vous ne connaissez pas
|
||
cette conférence, il s&#8217;agit d&#8217;un moment avec des gens chouettes qui se posent
|
||
des questions sur leur metier, comment le vivre et …</p></summary><content type="html"><p>Je vous écris depuis un train, en rentrant de Bordeaux où j&#8217;ai passé quelques
|
||
jours à l&#8217;occasion de <a href="http://sudweb.fr/">SudWeb</a>. Si vous ne connaissez pas
|
||
cette conférence, il s&#8217;agit d&#8217;un moment avec des gens chouettes qui se posent
|
||
des questions sur leur metier, comment le vivre et comment continuer à en faire
|
||
un plaisir. Oh, et des fois on parle un peu de technique&nbsp;aussi.</p>
|
||
<h1 id="alors-brasserie-ou-code">Alors, brasserie ou code&nbsp;?</h1>
|
||
<p>Ces quelques jours ont été fort inspirants. Alors que je suis en train de
|
||
changer de métier (vers celui de brasseur) c&#8217;était un moyen de me rendre compte
|
||
que bien que je ne souhaite plus faire du Web mon métier <em>la, tout de suite,
|
||
maintenant</em>, je reste un passionné par la&nbsp;chose.</p>
|
||
<p>En partant de Rennes, je ne savais pas trop quoi penser de cette situation.
|
||
Prendre un week-end pour échanger avec les gens sur quelque chose dont je
|
||
m&#8217;éloigne ? C&#8217;est pas une perte de temps&nbsp;?</p>
|
||
<p>Si je passe du temps à écrire des bouts de code, des logiciels, à reflechir
|
||
à comment solutionner certains problemes, ce n&#8217;est pas parce que je suis payé
|
||
pour le faire, mais bel et bien parce que je me sens bien lorsque je le fais,
|
||
parce que j&#8217;y trouve un équilibre et une&nbsp;utilité.</p>
|
||
<p>Alors que je ne trouvais plus cet équilibre dans mon travail, j&#8217;ai choisi d&#8217;en
|
||
changer, mais il n&#8217;empèche que je continue à avoir des rèves d&#8217;un
|
||
monde meilleur, dans lequel l&#8217;informatique a sa place. Juste à voir les
|
||
discussions (ux, sécurité informatique, décentralisation, architecture
|
||
logicielle) que j&#8217;ai pu avoir ce weekend, il n&#8217;y a pas l&#8217;ombre d&#8217;un doute&nbsp;!</p>
|
||
<p>Jusqu&#8217;ici je me suis dit que je devais choisir. J&#8217;ai pensé naivement
|
||
que je ne pouvais pas être <em>et</em> un brasseur <em>et</em> un developpeur, mais la
|
||
réalité c&#8217;est que c&#8217;est exactement ce que je suis: les&nbsp;deux.</p>
|
||
<p>Je ne suis pas pour autant dupe sur le temps necessaire à lancer une activité
|
||
brassicole, il va falloir fournir de l&#8217;énergie et avancer sur le projet, mais
|
||
il n&#8217;empèche que même si je décide de faire de la bière mon metier, mes
|
||
passions pour le reste sont bien&nbsp;vivantes.</p>
|
||
<p>Bref, merci sudweb pour m&#8217;avoir accompagné dans ces reflexions, à l&#8217;année
|
||
prochaine, je ramène des futs&nbsp;?</p></content><category term="journal"></category></entry><entry><title>Avez vous confiance en SSL?</title><link href="https://blog.notmyidea.org/avez-vous-confiance-en-ssl.html" rel="alternate"></link><published>2016-03-25T00:00:00+01:00</published><updated>2016-03-25T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-03-25:/avez-vous-confiance-en-ssl.html</id><summary type="html"><p>Dans le cadre <a href="http://autodefense-numerique.readthedocs.org/en/latest/">des ateliers d&#8217;autodéfense numérique</a>,
|
||
j&#8217;ai passé un peu de temps à creuser sur l&#8217;utilisation de <span class="caps">SSL</span> puisque
|
||
contrairement à ce que la plupart des personnes ont encore tendance à croire,
|
||
le petit cadenas (qui prouve qu&#8217;une connexion <span class="caps">SSL</span> est en cours) n&#8217;est …</p></summary><content type="html"><p>Dans le cadre <a href="http://autodefense-numerique.readthedocs.org/en/latest/">des ateliers d&#8217;autodéfense numérique</a>,
|
||
j&#8217;ai passé un peu de temps à creuser sur l&#8217;utilisation de <span class="caps">SSL</span> puisque
|
||
contrairement à ce que la plupart des personnes ont encore tendance à croire,
|
||
le petit cadenas (qui prouve qu&#8217;une connexion <span class="caps">SSL</span> est en cours) n&#8217;est
|
||
<strong>absolument</strong> pas&nbsp;suffisant.</p>
|
||
<p>Allez hop, c&#8217;est parti&nbsp;pour:</p>
|
||
<ul>
|
||
<li>un tour d&#8217;horizon du fonctionnement de&nbsp;SSl</li>
|
||
<li>quelques moyens contourner cette &#8220;protection&#8221; en faisant une attaque en&nbsp;pratique</li>
|
||
<li>un tour des solutions existantes actuellement et de pourquoi je ne les trouve
|
||
pas vraiment&nbsp;satisfaisantes.</li>
|
||
</ul>
|
||
<h2 id="comment-fonctionne-ssl">Comment fonctionne <span class="caps">SSL</span>?</h2>
|
||
<p>Pour expliquer les problèmes de <span class="caps">SSL</span>, j&#8217;ai d&#8217;abord besoin d&#8217;expliquer comment
|
||
tout ça&nbsp;fonctionne.</p>
|
||
<p><span class="caps">SSL</span> repose sur l&#8217;utilisation de certificats, qui sont générés par des autorités
|
||
de certification (<em>Certificate Authority</em> que je nomme <em><span class="caps">CA</span></em> dans la suite de&nbsp;l&#8217;article).</p>
|
||
<p>Les certificats <span class="caps">SSL</span> permettent deux&nbsp;choses:</p>
|
||
<ul>
|
||
<li>De garantir que les communications entre les navigateurs (vous) et les sites
|
||
Web ne sont connues que du détenteur du certificat du site et de vous&nbsp;même.</li>
|
||
<li>De garantir que le site sur lequel vous vous connectez est bien celui que
|
||
vous&nbsp;imaginez.</li>
|
||
</ul>
|
||
<p>Le navigateur, lors d&#8217;une visite d&#8217;un site, va télécharger le certificat
|
||
associé puis vérifier que le certificat en question a bien été généré par un
|
||
des <em><span class="caps">CA</span></em> en qui il a&nbsp;confiance.</p>
|
||
<p>Imaginons maintenant qu&#8217;une des <em><span class="caps">CA</span></em> essaye de savoir ce qui s&#8217;échange entre
|
||
mon navigateur et le site de ma banque (protégé par <span class="caps">SSL</span>). Comment cela se
|
||
passerait il&nbsp;?</p>
|
||
<p>N&#8217;importe quel <em><span class="caps">CA</span></em> peut donc générer des certificats pour n&#8217;importe quel site,
|
||
et le navigateur vérifierait, lui, que le certificat a bien été généré par une
|
||
<em><span class="caps">CA</span></em>.</p>
|
||
<p>Tout cela ne poserait pas de soucis si les <em><span class="caps">CA</span></em> étaient gérés de manière fiable,
|
||
mais il s&#8217;agit d&#8217;un travail compliqué, et certains <em><span class="caps">CA</span></em> ont par le passé montré
|
||
des&nbsp;faiblesses.</p>
|
||
<p>Par exemple, <a href="https://en.wikipedia.org/wiki/DigiNotar">DigiNotar</a> (un <em><span class="caps">CA</span></em> des Pays-Bas)
|
||
a été compromise et les attaquant.e.s ont pu générer des certificats <span class="caps">SSL</span>
|
||
frauduleux, ce qui leur a permis d&#8217;attaquer des sites tels que Facebook ou&nbsp;GMail.</p>
|
||
<p>Vous pouvez retrouver une liste des risques et menaces autour des <em><span class="caps">CA</span></em> <a href="http://wiki.cacert.org/Risk/History">sur le
|
||
wiki de CACert</a>.</p>
|
||
<h2 id="attaque-de-lhomme-du-milieu-avec-ssl">Attaque de l&#8217;homme du milieu avec <span class="caps">SSL</span></h2>
|
||
<p>A force de dire que c&#8217;était très facile à faire, j&#8217;ai eu envie d&#8217;essayer
|
||
d&#8217;espionner des connections protégées par <span class="caps">SSL</span>, et effectivement c&#8217;est
|
||
carrément flippant tellement c&#8217;est&nbsp;simple.</p>
|
||
<p>En l&#8217;espace de quelques minutes, il est possible de faire une <em>attaque de
|
||
l&#8217;homme du milieu</em> en utilisant par exemple un outil nommé <a href="http://docs.mitmproxy.org/en/stable">mitm-proxy</a>.</p>
|
||
<p>Pour déchiffrer l&#8217;ensemble du trafic <span class="caps">SSL</span>, j&#8217;ai simplement eu à lancer quelques
|
||
commandes et avoir un <em><span class="caps">CA</span></em> dans lequel le navigateur de la victime a confiance.
|
||
Je l&#8217;ai ajouté dans le navigateur cible pour simuler que je l&#8217;avais déjà
|
||
(c&#8217;est le cas si un des 1200 <span class="caps">CA</span> se fait pirater, ce qui me semble une surface
|
||
d&#8217;attaque assez&nbsp;large).</p>
|
||
<p>Je les colle ici si ça vous&nbsp;intéresse:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>sudo<span class="w"> </span>aptitude<span class="w"> </span>install<span class="w"> </span>mitmproxy
|
||
$<span class="w"> </span>mitm-proxy<span class="w"> </span>-T<span class="w"> </span>--host
|
||
</code></pre></div>
|
||
|
||
<p>Il faut faire croire à votre victime que vous êtes la passerelle vers
|
||
l&#8217;extérieur et à la passerelle que vous êtes la&nbsp;victime:</p>
|
||
<div class="highlight"><pre><span></span><code>arpspoof<span class="w"> </span>-i<span class="w"> </span>wlan0<span class="w"> </span>-t<span class="w"> </span>victime<span class="w"> </span>gateway
|
||
arpspoof<span class="w"> </span>-i<span class="w"> </span>wlan0<span class="w"> </span>-t<span class="w"> </span>gateway<span class="w"> </span>victime
|
||
</code></pre></div>
|
||
|
||
<p>Puis dire à notre fausse passerelle de rediriger le trafic des ports 80 et 443
|
||
vers notre&nbsp;proxy:</p>
|
||
<div class="highlight"><pre><span></span><code>sudo<span class="w"> </span>sysctl<span class="w"> </span>-w<span class="w"> </span>net.ipv4.ip_forward<span class="o">=</span><span class="m">1</span>
|
||
sudo<span class="w"> </span>iptables<span class="w"> </span>-t<span class="w"> </span>nat<span class="w"> </span>-A<span class="w"> </span>PREROUTING<span class="w"> </span>-i<span class="w"> </span>wlan0<span class="w"> </span>-p<span class="w"> </span>tcp<span class="w"> </span>--dport<span class="w"> </span><span class="m">443</span><span class="w"> </span>-j<span class="w"> </span>REDIRECT<span class="w"> </span>--to-port<span class="w"> </span><span class="m">4443</span>
|
||
sudo<span class="w"> </span>iptables<span class="w"> </span>-t<span class="w"> </span>nat<span class="w"> </span>-A<span class="w"> </span>PREROUTING<span class="w"> </span>-i<span class="w"> </span>wlan0<span class="w"> </span>-p<span class="w"> </span>tcp<span class="w"> </span>--dport<span class="w"> </span><span class="m">80</span><span class="w"> </span>-j<span class="w"> </span>REDIRECT<span class="w"> </span>--to-port<span class="w"> </span><span class="m">4443</span>
|
||
</code></pre></div>
|
||
|
||
<p>Et paf, <strong>on voit tout ce qui passe entre la machine et le serveur <span class="caps">SSL</span></strong>. On peut
|
||
d&#8217;ailleurs même imaginer faire tourner ces quelques commandes sur un
|
||
raspberry pi, pour aller encore plus&nbsp;vite…</p>
|
||
<h3 id="key-pinning-dans-les-navigateurs">Key-pinning dans les&nbsp;navigateurs</h3>
|
||
<p>Actuellement, n&#8217;importe quel <em><span class="caps">CA</span></em> peut générer des certificats pour
|
||
n&#8217;importe quel site, et c&#8217;est en grande partie ce qui pose souci. Une des
|
||
manières de faire évoluer la situation est d&#8217;épingler les certificats de
|
||
certains sites directement dans les&nbsp;navigateurs.</p>
|
||
<p>Cette approche a le mérite de fonctionner très bien <a href="https://dxr.mozilla.org/mozilla-central/source/security/manager/ssl/StaticHPKPins.h?from=StaticHPKPins.h">pour un petit nombre de
|
||
sites critiques (Google, Facebook, etc)</a>.</p>
|
||
<h3 id="http-public-key-pinning-hpkp"><span class="caps">HTTP</span> Public Key Pinning (<span class="caps">HPKP</span>)</h3>
|
||
<p><a href="https://developer.mozilla.org/en/docs/Web/Security/Public_Key_Pinning"><em><span class="caps">HTTP</span> Public Key Pinning</em></a>
|
||
est également une solution de <em>pinning</em> qui permet d&#8217;établir une confiance lors
|
||
de la première connexion avec le site. C&#8217;est ce qu&#8217;on appelle du <em>Trust on First
|
||
Use</em> ou <em><span class="caps">TOFU</span></em>.</p>
|
||
<p>Le navigateur va alors mettre ces informations dans un cache et vérifiera que
|
||
les certificats correspondent bien lors des prochaines&nbsp;visites.</p>
|
||
<p><em><span class="caps">HPKP</span></em> est disponible dans Firefox depuis Janvier 2015 et dans Chrome
|
||
depuis Octobre&nbsp;2015.</p>
|
||
<h3 id="certificate-transparency-des-journaux-auditables">Certificate transparency: des journaux&nbsp;auditables</h3>
|
||
<p>Une autre approche est celle proposée par <em>certificate transparency</em>:</p>
|
||
<blockquote>
|
||
<p>Certificate Transparency aims to remedy these certificate-based threats by
|
||
making the issuance and existence of <span class="caps">SSL</span> certificates open to scrutiny by
|
||
domain owners, CAs, and domain&nbsp;users.</p>
|
||
<p>&#8212; <a href="https://www.certificate-transparency.org/what-is-ct">Certificate&nbsp;Transparency</a></p>
|
||
</blockquote>
|
||
<p>Autrement dit, avec ce système les <em><span class="caps">CA</span></em> doivent rendre public le fait qu&#8217;ils
|
||
aient signé de nouveaux certificats intermédiaires. La signature est ajoutée à
|
||
un journal sur lequel il n&#8217;est possible que&nbsp;d&#8217;écrire.</p>
|
||
<p>Les navigateurs vont alors vérifier que les certificats utilisés sont bien des
|
||
certificats qui ont été ajoutés au&nbsp;journal.</p>
|
||
<p>Ici, toute l&#8217;intelligence est dans la vérification de ces journaux, qui
|
||
permettent donc de valider/invalider des certificats racines ou&nbsp;intermédiaires.</p>
|
||
<p>Il me semble donc qu&#8217;il serait possible d&#8217;ajouter un certificat frauduleux le
|
||
temps d&#8217;une attaque (et celui ci serait détecté et supprimé&nbsp;ensuite).</p>
|
||
<p><em>Certificate-Transparency</em> n&#8217;est donc pas une solution contre une écoute
|
||
globale mise en place par les gouvernements par&nbsp;exemple.</p>
|
||
<p>Si vous lisez bien l&#8217;anglais, je vous invite à aller lire
|
||
<a href="http://security.stackexchange.com/a/52838">cette description du problème et de la solution</a>
|
||
que je trouve très bien&nbsp;écrite.</p>
|
||
<h3 id="dane-dnssec"><span class="caps">DANE</span> + <span class="caps">DNSSEC</span></h3>
|
||
<blockquote>
|
||
<p>The <span class="caps">DANE</span> working group has developed a framework for securely
|
||
retrieving keying information from the <span class="caps">DNS</span> [<span class="caps">RFC6698</span>]. This
|
||
framework allows secure storing and looking up server public key
|
||
information in the <span class="caps">DNS</span>. This provides a binding between a domain
|
||
name providing a particular service and the key that can be used
|
||
to establish encrypted connection to that&nbsp;service.</p>
|
||
<p>&#8212; <a href="https://datatracker.ietf.org/wg/dane/charter/">Dane <span class="caps">WG</span></a></p>
|
||
</blockquote>
|
||
<p>Une autre solution est appelée &#8220;<span class="caps">DANE</span>&#8221; et repose par dessus le protocole
|
||
<em><span class="caps">DNSSEC</span></em>.</p>
|
||
<p>Je connais assez mal <em><span class="caps">DNSSEC</span></em> donc j&#8217;ai passé un peu de temps à lire des
|
||
documents. L&#8217;impression finale que ça me laisse est que le problème est
|
||
exactement le même que pour <span class="caps">SSL</span>: un certain nombre de personnes détiennent les
|
||
clés et toute la sécurité repose sur cette confiance. Or il est possible que
|
||
ces clés soient détenues par des personnes non dignes de&nbsp;confiance.</p>
|
||
<blockquote>
|
||
<p>Secure <span class="caps">DNS</span> (<span class="caps">DNSSEC</span>) uses cryptographic digital signatures signed with a
|
||
trusted public key certificate to determine the authenticity of data.
|
||
&#8212;&nbsp;https://en.wikipedia.org/wiki/DNS_spoofing</p>
|
||
</blockquote>
|
||
<p>Et&nbsp;aussi:</p>
|
||
<blockquote>
|
||
<p>It is widely believed[1] that securing the <span class="caps">DNS</span> is critically important for
|
||
securing the Internet as a whole, but deployment of <span class="caps">DNSSEC</span> specifically has
|
||
been hampered (As of 22 January 2010) by several&nbsp;difficulties:</p>
|
||
<ul>
|
||
<li>The need to design a backward-compatible standard that can scale to the
|
||
size of the&nbsp;Internet</li>
|
||
<li>Prevention of &#8220;zone enumeration&#8221; (see below) where&nbsp;desired</li>
|
||
<li>Deployment of <span class="caps">DNSSEC</span> implementations across a wide variety of <span class="caps">DNS</span> servers
|
||
and resolvers&nbsp;(clients)</li>
|
||
<li>Disagreement among implementers over who should own the top-level domain
|
||
root keys Overcoming the perceived complexity of <span class="caps">DNSSEC</span> and <span class="caps">DNSSEC</span>&nbsp;deployment</li>
|
||
</ul>
|
||
</blockquote>
|
||
<h2 id="solutions-basees-sur-la-blockchain">Solutions basées sur la&nbsp;blockchain</h2>
|
||
<p>Une dernière piste semble être l&#8217;utilisation de la <em>blockchain</em> pour distribuer
|
||
des clés par&nbsp;site.</p>
|
||
<p>La solution <em>DNSChain</em> me paraissait tout d&#8217;abord un bon point de départ mais
|
||
la lecture de <a href="https://www.indolering.com/okturtles-dnschain-unblock-us">quelques critiques</a>
|
||
et interventions du développeur du projet m&#8217;ont fait changer&nbsp;d&#8217;avis.</p>
|
||
<p>Reste encore la piste de <em>Namecoin Control</em> que je n&#8217;ai pas encore creusée.
|
||
Peut-être pour un prochain billet. Toute piste de réflexion est bien sur la
|
||
bienvenue sur ces&nbsp;sujets!</p></content><category term="code"></category></entry><entry><title>Focusing on what matters</title><link href="https://blog.notmyidea.org/focusing-on-what-matters.html" rel="alternate"></link><published>2016-03-17T00:00:00+01:00</published><updated>2016-03-17T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-03-17:/focusing-on-what-matters.html</id><summary type="html"><p>I do have a problem with&nbsp;information.</p>
|
||
<p>You know. I <strong>have</strong> to check my emails, irc, twitter, my feed reader
|
||
etc. I need&nbsp;to.</p>
|
||
<p>And this thing makes me feel uncomfortable at the end of the day,
|
||
because I feel that I missed something. That I missed some good time …</p></summary><content type="html"><p>I do have a problem with&nbsp;information.</p>
|
||
<p>You know. I <strong>have</strong> to check my emails, irc, twitter, my feed reader
|
||
etc. I need&nbsp;to.</p>
|
||
<p>And this thing makes me feel uncomfortable at the end of the day,
|
||
because I feel that I missed something. That I missed some good time,
|
||
away from news and&nbsp;agitation.</p>
|
||
<p>Working remotely is sometimes hard. Hard because you need to at the same
|
||
time be in the discussions channels and work on the interesting
|
||
projects. A real&nbsp;myth.</p>
|
||
<p>In practice, I&#8217;m really bad at multi-tasking. I tried a few times the
|
||
<em>Pomodoro</em> technique, which forces me to focus on a task for 25mn, but
|
||
this split of my day into slices of 25mn breaks my natural&nbsp;flow.</p>
|
||
<p>So, what do I need? I tried to change my tools, it helped a bit. Still,
|
||
I&#8217;m not focused like I would like to&nbsp;be.</p>
|
||
<p>Maybe that&#8217;s just me who needs some more persuasion over myself, but the
|
||
best way I found to work is to unplug the cable. Literally. At work, at
|
||
some point I was using a <span class="caps">RJ45</span> cable to connect to the Internet. When I
|
||
wanted to work on something, I could just unplug this&nbsp;cable.</p>
|
||
<p>And that&#8217;s amazing how you find yourself in the process to &#8220;check&#8221;
|
||
something on the web. Mails, irc… well, you got the idea. You&#8217;re
|
||
litterally, without even noticing, switching to your browser an opening
|
||
a new&nbsp;tab…</p>
|
||
<p>Of course, that Web isn&#8217;t filled only with lolcats and twitter messages
|
||
(even if I would <strong>love</strong> to see a pie chart with the repartition of
|
||
lolcats <span class="caps">VS</span> the rest of the web&#8217;s content), so sometimes you need some
|
||
precious bit of information that&#8217;s there. Fair enough. plug the cable,
|
||
do what you <strong>need</strong> to do, and unplug. Alexis,&nbsp;unplug!</p>
|
||
<p>It also helps to have some fair bit of documentation available directly
|
||
on my machine (I used to have the python docs, I should get it&nbsp;back!)</p>
|
||
<p>I&#8217;m feeling adventurous, so I&#8217;ll try something new starting tomorrow,
|
||
and I&#8217;ll report back in here my findings. Here&#8217;s the&nbsp;challenge:</p>
|
||
<ul>
|
||
<li><strong>Check emails only once a day</strong>. Do <strong>not</strong> do it in the morning,
|
||
before working, to keep my mind clear. I would say at 2pm (after
|
||
lunch). (This doesn&#8217;t mean I will not send mails&nbsp;tho)</li>
|
||
<li>Stay away from the Internet during the morning. I&#8217;ll not connect if
|
||
I don&#8217;t need&nbsp;to.</li>
|
||
</ul>
|
||
<p>Let&#8217;s see how it goes&nbsp;:)</p></content><category term="journal"></category></entry><entry><title>Retours sur un atelier ZeroNet</title><link href="https://blog.notmyidea.org/retours-sur-un-atelier-zeronet.html" rel="alternate"></link><published>2016-03-17T00:00:00+01:00</published><updated>2016-03-17T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-03-17:/retours-sur-un-atelier-zeronet.html</id><summary type="html"><p>Mardi dernier se tenait <a href="http://biblio.insa-rennes.fr/crypto">une <em>cryptoparty</em></a> dans les locaux de l&#8217;<span class="caps">INSA</span> de&nbsp;Rennes.</p>
|
||
<p>L&#8217;évènement s&#8217;étant rempli au delà de toutes les espérances, on m&#8217;a proposé de
|
||
venir y tenir un atelier, que j&#8217;ai proposé sur <a href="https://zeronet.io">ZeroNet</a>, un
|
||
petit projet fort sympathique qui pourrait devenir une …</p></summary><content type="html"><p>Mardi dernier se tenait <a href="http://biblio.insa-rennes.fr/crypto">une <em>cryptoparty</em></a> dans les locaux de l&#8217;<span class="caps">INSA</span> de&nbsp;Rennes.</p>
|
||
<p>L&#8217;évènement s&#8217;étant rempli au delà de toutes les espérances, on m&#8217;a proposé de
|
||
venir y tenir un atelier, que j&#8217;ai proposé sur <a href="https://zeronet.io">ZeroNet</a>, un
|
||
petit projet fort sympathique qui pourrait devenir une nouvelle manière de
|
||
distribuer le Web, permettant notamment d&#8217;éviter la&nbsp;censure.</p>
|
||
<p>Avant toute autre chose, merci énormément à l&#8217;équipe de la bibliothèque de
|
||
l&#8217;<span class="caps">INSA</span> pour l&#8217;organisation de cet évènement qui à une réelle portée&nbsp;politique.</p>
|
||
<h2 id="un-peu-dhistoire">Un peu&nbsp;d&#8217;histoire</h2>
|
||
<p>Il me semble que Tim Bernes Lee (l&#8217;inventeur du Web) avait prévu le Web comme un
|
||
protocole décentralisé. Chacun hébergerait ses données et les servirait aux
|
||
autres, qui pourraient alors y&nbsp;accéder.</p>
|
||
<p>Avec ce fonctionnement, impossible alors d&#8217;accéder à des sites si leur auteur
|
||
n&#8217;est pas en ligne. Qu&#8217;à cela ne tienne, on s&#8217;est mis à avoir des machines qui
|
||
restent connectées au réseau 24 heures par jour. Et puis une machine ne
|
||
suffisant plus, on a eu des fermes de machines dans des <em>data centers</em> etc afin
|
||
de supporter les milliers d&#8217;utilisateurs des&nbsp;sites.</p>
|
||
<h2 id="un-web-decentralise">Un Web&nbsp;décentralisé</h2>
|
||
<p>ZeroNet permet (entre autres) de répondre à ce problème en proposant une manière alternative de <strong>distribuer le Web</strong>, en pair à pair. Lors d&#8217;une visite d&#8217;un&nbsp;site:</p>
|
||
<ol>
|
||
<li>Vous contactez un <em>tracker</em> BitTorrent pour connaitre la liste des autres
|
||
visiteurs du site (les <em>pairs</em>).</li>
|
||
<li>Vous demandez aux <em>pairs</em> de vous donner les fichiers du&nbsp;site.</li>
|
||
<li>Vous validez que les fichiers servis sont bien les bons (en vérifiant la
|
||
signature&nbsp;attachée).</li>
|
||
</ol>
|
||
<p>N&#8217;importe quel visiteur devient alors un <em>pair</em>, qui sert le site aux autres&nbsp;visiteurs.</p>
|
||
<p>Parmi les nombreux avantages de cette approche, je note particulièrement&nbsp;que:</p>
|
||
<ul>
|
||
<li>Il est très difficile de censurer un site — Il est sur l&#8217;ensemble des machines
|
||
des&nbsp;visiteurs.</li>
|
||
<li>Les attaques par <em>fingerprinting</em> sont impossibles: le navigateur Web se
|
||
connecte à un serveur <em>proxy</em>&nbsp;local.</li>
|
||
<li>Vous détenez directement vos données et (par design) ne les donnez pas à des
|
||
silos (Facebook, Google,&nbsp;etc.)</li>
|
||
</ul>
|
||
<p>Si vous êtes interessés par une démonstration rapide, j&#8217;ai enregistré une vidéo
|
||
de 10 minutes où je parle en anglais avec une voix très&nbsp;grave.</p>
|
||
<video controls="" src="http://alexis.notmyidea.org/zeronet.webm" width=800></video>
|
||
|
||
<h2 id="atelier">Atelier</h2>
|
||
<p>Pour l&#8217;atelier, j&#8217;ai choisi de faire une présentation rapide du projet (<a href="https://blog.notmyidea.org/docs/zeronet-presentation-fr.pdf">j&#8217;ai
|
||
traduit les slides</a> anglais
|
||
pour l&#8217;occasion — <a href="https://docs.google.com/presentation/d/158C_-V1ueNaaKHMBMBgGOVhunb9xrXzB3hC_g1N53c0/edit?usp=sharing">accès aux sources</a>)
|
||
avant d&#8217;installer ZeroNet sur les machines et de l&#8217;utiliser pour publier un&nbsp;site.</p>
|
||
<h3 id="partager-sur-le-reseau-local">Partager sur le réseau&nbsp;local</h3>
|
||
<p>Nous avons eu des soucis à cause du réseau (un peu congestionné) sur lequel
|
||
les ports utilisés pour la discussion entre <em>pairs</em> étaient fermés. Il est bien
|
||
sur possible de faire tourner le tout de manière indépendante du reste du réseau,
|
||
mais je n&#8217;avais pas prévu le&nbsp;coup.</p>
|
||
<p>Voici donc comment faire pour contourner le&nbsp;souci:</p>
|
||
<ol>
|
||
<li>Installer et lancer un <em>tracker</em> BitTorrent (De manière surprenante,
|
||
<a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=685575">rien n&#8217;est packagé pour debian pour l&#8217;instant</a>)
|
||
J&#8217;ai choisi d&#8217;installer <a href="http://erdgeist.org/arts/software/opentracker/#build-instructions">OpenTracker</a></li>
|
||
<li>Ensuite lancer ZeroNet avec des options&nbsp;spécifiques.</li>
|
||
</ol>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>zeronet.py<span class="w"> </span>--trackers<span class="w"> </span>udp://localhost:6969<span class="w"> </span>--ip_external<span class="w"> </span><span class="m">192</span>.168.43.207
|
||
$<span class="w"> </span>python<span class="w"> </span>zeronet.py<span class="w"> </span>--trackers<span class="w"> </span>udp://192.168.43.207:6969<span class="w"> </span>--ip_external<span class="w"> </span><span class="m">192</span>.168.43.172
|
||
</code></pre></div>
|
||
|
||
<p>Il est nécessaire de spécifier l&#8217;adresse <span class="caps">IP</span> externe que chaque nœud expose pour
|
||
éviter qu&#8217;elle n&#8217;essaye d&#8217;aller la trouver par elle même: nous voulons l&#8217;adresse
|
||
du réseau local, et non pas l&#8217;adresse&nbsp;internet.</p>
|
||
<p>La prochaine fois je tenterais de venir avec un HotSpot Wifi et un tracker
|
||
BitTorrent dans la&nbsp;poche!</p>
|
||
<h2 id="questions-reponses">Questions /&nbsp;Réponses</h2>
|
||
<p>Il y avait quelques questions intéressantes auxquelles je n&#8217;ai pas toujours su
|
||
répondre sur le moment. Après quelques recherches, je rajoute des détails&nbsp;ici.</p>
|
||
<h3 id="torrent-tor-breche-de-secu">Torrent + Tor = brèche de sécu&nbsp;?</h3>
|
||
<p>Il me semblait avoir entendu parler de problèmes de <em>dé-anonymisation</em>
|
||
<a href="https://hal.inria.fr/file/index/docid/471556/filename/TorBT.pdf">lors de l&#8217;utilisation de BitTorrent par dessus Tor</a>.</p>
|
||
<blockquote>
|
||
<p>Dans certains cas, certains clients torrents (uTorrent, BitSpirit, etc)
|
||
écrivent directement votre adresse <span class="caps">IP</span> dans l&#8217;information qui est envoyée
|
||
au tracker et/ou aux autres pairs.
|
||
—&nbsp;https://blog.torproject.org/blog/bittorrent-over-tor-isnt-good-idea</p>
|
||
</blockquote>
|
||
<p><a href="https://github.com/HelloZeroNet/ZeroNet/issues/274">Ce n&#8217;est pas le cas de ZeroNet</a>, ce qui évacue le&nbsp;souci.</p>
|
||
<h3 id="zeromail-cest-lent-non">ZeroMail, c&#8217;est lent non&nbsp;?</h3>
|
||
<p>Une des applications de démo, <em>ZeroMail</em>, propose un mécanisme qui permet de
|
||
s&#8217;envoyer des messages chiffrés sur un réseau pair à pair. L&#8217;approche choisie
|
||
est de chiffrer les messages avec la clé du destinataire et de le mettre dans
|
||
un <em>pot commun</em>. Tout le monde essaye de déchiffrer tous les messages, mais ne
|
||
peut déchiffrer que les&nbsp;siens.</p>
|
||
<p>Cela permet de ne <strong>pas</strong> fuiter de méta-données, <a href="https://blog.notmyidea.org/les-problemes-de-pgp.html">à l&#8217;inverse de <span class="caps">PGP</span></a>.</p>
|
||
<p>Je n&#8217;ai en fait pas de réponse claire à donner à cette question: l&#8217;auteur de
|
||
ZeroNet me disait que <span class="caps">10MB</span> (la limite de taille d&#8217;un site, par défaut)
|
||
correspondait à beaucoup de place pour stocker des messages, et qu&#8217;il était
|
||
possible de supprimer les anciens messages une fois qu&#8217;ils sont lus par&nbsp;exemple.</p>
|
||
<p>Une autre solution à laquelle je pensait était de créer un <em>ZeroSite</em> pour
|
||
chaque récipient, mais on connait à ce moment là le nombre de messages qu&#8217;un
|
||
utilisateur peut&nbsp;recevoir.</p>
|
||
<p>Je vois plusieurs problèmes avec le design actuel de ZeroMail (il me semble
|
||
assez facile d&#8217;y faire un déni de service par exemple). A&nbsp;creuser.</p>
|
||
<h3 id="comment-heberger-des-tres-gros-sites">Comment héberger des très gros sites&nbsp;?</h3>
|
||
<p>Par exemple, comment faire pour héberger Wikipedia&nbsp;?</p>
|
||
<p>Il semble que la meilleure manière de faire serait de séparer Wikipedia en
|
||
un tas de petites ressources (par catégorie par ex.). Les gros médias pourraient
|
||
être considérés optionnels (et donc téléchargés uniquement à la&nbsp;demande)</p>
|
||
<h3 id="est-ce-quon-a-vraiment-besoin-dun-tracker">Est-ce qu&#8217;on à vraiment besoin d&#8217;un tracker&nbsp;?</h3>
|
||
<p>Le support d&#8217;une <span class="caps">DHT</span> <a href="https://github.com/HelloZeroNet/ZeroNet/issues/57">est souhaité</a>,
|
||
mais pour l&#8217;instant pas encore implémenté. L&#8217;utilisation de la <span class="caps">DHT</span> BitTorrent
|
||
n&#8217;est pas une option puisque <a href="https://github.com/HelloZeroNet/ZeroNet/issues/57">Tor ne supporte pas <span class="caps">UDP</span></a>.</p></content><category term="code"></category></entry><entry><title>L’horizon</title><link href="https://blog.notmyidea.org/lhorizon.html" rel="alternate"></link><published>2016-03-02T00:00:00+01:00</published><updated>2016-03-02T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-03-02:/lhorizon.html</id><summary type="html"><p>headline : Temps de changer d&#8217;horizon. Mon départ de Mozilla et le début d&#8217;une nouvelle histoire.
|
||
image :&nbsp;images/horizon.jpg</p>
|
||
<blockquote>
|
||
<p>L&#8217;Utopie, c&#8217;est l&#8217;horizon. C&#8217;est ce qui permet d&#8217;avoir une direction,
|
||
de mettre un pied devant l&#8217;autre, de savoir vers où&nbsp;marcher.</p>
|
||
</blockquote>
|
||
<p>Il y …</p></summary><content type="html"><p>headline : Temps de changer d&#8217;horizon. Mon départ de Mozilla et le début d&#8217;une nouvelle histoire.
|
||
image :&nbsp;images/horizon.jpg</p>
|
||
<blockquote>
|
||
<p>L&#8217;Utopie, c&#8217;est l&#8217;horizon. C&#8217;est ce qui permet d&#8217;avoir une direction,
|
||
de mettre un pied devant l&#8217;autre, de savoir vers où&nbsp;marcher.</p>
|
||
</blockquote>
|
||
<p>Il y a presque 4 ans et demi, je commençais à travailler, en décembre,
|
||
pour Mozilla. Je me rappelle bien de ces premiers instants un peu
|
||
magiques, qui ont eu lieu juste avant une descente de cave en Bourgogne
|
||
avec Tarek pour y déguster quelques saveurs de vins&nbsp;différentes.</p>
|
||
<p>Quatre ans plus tard, je me retrouve à coder sur Daybed, mon petit
|
||
projet perso, devenu <a href="http://kinto.readthedocs.org/">Kinto</a> avec une
|
||
équipe de personnes plus talentueuses et sympathiques les unes que les
|
||
autres (Niko, Rémy, Mat, si vous me&nbsp;lisez…).</p>
|
||
<p>Mozilla a bien évolué en quelques années: les petits bureaux ou j&#8217;avais
|
||
atterri se sont transformés en palace où il est possible d&#8217;accueillir
|
||
des membres de la communauté du logiciel libre de manière&nbsp;quotidienne.</p>
|
||
<p>De 14 personnes dans les bureaux Parisiens, nous sommes passés à une
|
||
40aine (et de \~500 salariés à 1100 dans le&nbsp;monde).</p>
|
||
<p>Grandir autant en si peu de temps est un challenge difficile à tenir,
|
||
qui nécessite des réorganisations et bien souvent dans une structure de
|
||
cette taille, de la hiérarchisation. En 4 ans j&#8217;ai eu au moins 5
|
||
changements de supérieurs, pour finalement arriver à une situation
|
||
plutôt convenable (mais quand même&nbsp;!)</p>
|
||
<p>J&#8217;ai choisi de rejoindre Mozilla parce que j&#8217;ai besoin de causes à
|
||
défendre, qui me saisissent et qui me guident. Aujourd&#8217;hui, une des
|
||
visions qui m&#8217;anime, c&#8217;est celle que d&#8217;autres ont déjà ouverte: celle de
|
||
données et de vie privée qui sont rendues à leurs&nbsp;utilisateurs.</p>
|
||
<p>Et je veux faire en sorte de réaliser ces «rêves d&#8217;un monde meilleur»,
|
||
ce qui veut dire pour moi qu&#8217;il est temps de partir vers des horizons
|
||
plus propices à cette&nbsp;vision.</p>
|
||
<p>Lesquels ? Cela reste à construire (mais je vous le dis, y&#8217;a du Kinto
|
||
dedans&nbsp;!)</p>
|
||
<h2 id="la-suite">La suite&nbsp;?</h2>
|
||
<p>Sans m&#8217;étaler, je veux prendre du temps pour quelques projets autour du
|
||
stockage de données (via Kinto), de l&#8217;auto défense numérique (via des
|
||
formations) et de la fabrication de bière artisanale (parce que bon, on
|
||
se refait pas&nbsp;!)</p>
|
||
<p>Évidemment, plein d&#8217;envies diverses et variées, envie de me balader un
|
||
peu et d&#8217;expérimenter des choses&nbsp;collectivement&#8230;</p>
|
||
<p>On se recroisera surement&nbsp;:)</p></content><category term="journal"></category></entry><entry><title>Service de nuages : Garantir l’intégrité des données via des signatures</title><link href="https://blog.notmyidea.org/service-de-nuages-garantir-lintegrite-des-donnees-via-des-signatures-fr.html" rel="alternate"></link><published>2016-03-01T00:00:00+01:00</published><updated>2016-03-01T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-03-01:/service-de-nuages-garantir-lintegrite-des-donnees-via-des-signatures-fr.html</id><summary type="html"><p class="first last">Comment garantir l&#8217;intégrité des données en utilisant les&nbsp;signatures.</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p>Dans le cadre du projet <a class="reference external" href="https://wiki.mozilla.org/Firefox/Go_Faster">Go Faster</a>, nous souhaitons distribuer des
|
||
mises à jour de parties de <em>Firefox</em> de manière séparée des mises à jour majeures
|
||
(qui ont lieu toutes les 6&nbsp;semaines).</p>
|
||
<p>Les données que nous souhaitons mettre à jour sur les clients sont multiples.
|
||
Entre autres, nous souhaitons gérer <a class="reference external" href="https://blog.mozilla.org/security/2015/03/03/revoking-intermediate-certificates-introducing-onecrl/">la mise à jour des listes de révocation
|
||
(<span class="caps">CRL</span>) de certificats <span class="caps">SSL</span></a>.</p>
|
||
<p>Il est évidemment nécessaire de s&#8217;assurer que les données qui sont téléchargées
|
||
sur les client sont légitimes : que personne ne tente d&#8217;invalider des
|
||
certificats alors qu&#8217;ils sont valides, et que l&#8217;ensemble des mises à jour sont
|
||
bel et bien récupérées sur le&nbsp;client.</p>
|
||
<p>La signature garantit qu&#8217;une mise à jour contient tous les enregistrements, mais il
|
||
est toujours possible de bloquer l&#8217;accès au service (par exemple avec le <em>china
|
||
great firewall</em>).</p>
|
||
<p>Ce mécanisme fonctionne pour les listes de certificats à révoquer, mais pas
|
||
uniquement. Nous comptons réutiliser ce même fonctionnement dans le futur pour
|
||
la mise à jour d&#8217;autres parties de Firefox, et vous pouvez également en tirer
|
||
parti pour d&#8217;autres cas&nbsp;d&#8217;utilisation.</p>
|
||
<p>Nous souhaitons utiliser <a class="reference external" href="https://kinto.readthedocs.org">Kinto</a> afin
|
||
de distribuer ces jeux de données. Un des avantages est que l&#8217;on peut
|
||
facilement <em>cacher</em> les collections derrière un <span class="caps">CDN</span>.</p>
|
||
<p>Par contre, nous ne souhaitons pas que les clients fassent
|
||
confiance aveuglément, ni au serveur Kinto, ni au <span class="caps">CDN</span>.</p>
|
||
<p>Effectivement, un attaquant, contrôlant l&#8217;un ou l&#8217;autre, pourrait
|
||
alors envoyer les mises à jour qu&#8217;il souhaite à l&#8217;ensemble des clients
|
||
ou supprimer des certificats révoqués. Imaginez le carnage&nbsp;!</p>
|
||
<p>Afin de résoudre ce problème, considérons les conditions&nbsp;suivantes:</p>
|
||
<ul class="simple">
|
||
<li>La personne qui a le pouvoir de mettre à jour les <span class="caps">CRL</span> (<em>l&#8217;updater</em>)
|
||
a accès à une cle de signature (ou mieux, <a class="reference external" href="https://fr.wikipedia.org/wiki/Hardware_Security_Module">un <span class="caps">HSM</span></a>) qui lui permet de
|
||
signer la&nbsp;collection;</li>
|
||
<li>Le pendant public de ce certificat est stocké et distribué dans&nbsp;Firefox;</li>
|
||
<li>Le <em>hashing</em> et la <em>signature</em> sont faits côté client pour éviter certains
|
||
vecteurs d&#8217;attaque (si un attaquant a la main sur le serveur Kinto par&nbsp;exemple).</li>
|
||
</ul>
|
||
<p>Le chiffrement à sens unique, aussi appellé <em>hashing</em> est un moyen de toujours
|
||
obtenir le même résultat à partir de la même&nbsp;entrée.</p>
|
||
<div class="section" id="premier-envoi-de-donnees-sur-kinto">
|
||
<h2>Premier envoi de données sur&nbsp;Kinto</h2>
|
||
<p>L&#8217;ensemble des données est récupéré depuis une source <em>sécurisée</em> puis mis dans
|
||
une collection <span class="caps">JSON</span>. Chaque élément contient un identifiant unique généré sur
|
||
le&nbsp;client.</p>
|
||
<p>Par exemple, un enregistrement peut ressembler à&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;b7dded96-8df0-8af8-449a-8bc47f71b4c4&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s2">&quot;fingerprint&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;11:D5:D2:0A:9A:F8:D9:FC:23:6E:5C:5C:30:EC:AF:68:F5:68:FB:A3&quot;</span><span class="p">}</span>
|
||
</pre></div>
|
||
<p>Le <em>hash</em> de la collection est ensuite calculé, signé puis envoyé au serveur
|
||
(voir plus bas pour les&nbsp;détails).</p>
|
||
<p>La signature est déportée sur un service qui ne s&#8217;occupe que de ça, puisque la
|
||
sécurité du certificat qui s&#8217;occupe des signatures est extrêmement&nbsp;importante.</p>
|
||
</div>
|
||
<div class="section" id="comment-verifier-l-integrite-des-donnees">
|
||
<h2>Comment vérifier l&#8217;intégrité des données&nbsp;?</h2>
|
||
<p>Premièrement, il faut récupérer l&#8217;ensemble des enregistrements présents sur
|
||
le serveur, ainsi que le <em>hash</em> et la signature&nbsp;associée.</p>
|
||
<p>Ensuite, vérifier la signature du <em>hash</em>, pour s&#8217;assurer que celui-ci provient
|
||
bien d&#8217;un tiers de&nbsp;confiance.</p>
|
||
<p>Finalement, recalculer le <em>hash</em> localement et valider qu&#8217;il correspond bien à
|
||
celui qui a été&nbsp;signé.</p>
|
||
</div>
|
||
<div class="section" id="ajouter-de-nouvelles-donnees">
|
||
<h2>Ajouter de nouvelles&nbsp;données</h2>
|
||
<p>Pour l&#8217;ajout de nouvelles données, il est nécessaire de s&#8217;assurer que les
|
||
données que l&#8217;on a localement sont valides avant de faire quoi que ce soit&nbsp;d&#8217;autre.</p>
|
||
<p>Une fois ces données validées, il suffit de procéder comme la première fois, et
|
||
d&#8217;envoyer à nouveau le <em>hash</em> de la collection au&nbsp;serveur.</p>
|
||
</div>
|
||
<div class="section" id="comment-calculer-ce-hash">
|
||
<h2>Comment calculer ce hash&nbsp;?</h2>
|
||
<p>Pour calculer le <em>hash</em> de la collection, il est nécessaire&nbsp;:</p>
|
||
<ol class="arabic simple">
|
||
<li>D&#8217;ordonner l&#8217;ensemble des éléments de la collection (par leur id)&nbsp;;</li>
|
||
<li>Pour chaque élément, sérialiser les champs qui nous intéressent (les
|
||
concaténer clé +&nbsp;valeur)</li>
|
||
<li>Calculer le <em>hash</em> depuis la&nbsp;sérialisation.</li>
|
||
</ol>
|
||
<p>Nous sommes encore incertains de la manière dont le hash va être calculé. Les <a class="reference external" href="https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41"><span class="caps">JSON</span> Web Signature</a> semblent
|
||
une piste intéressante. En attendant, une implementation naïve en python
|
||
pourrait ressembler à ceci&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">json</span>
|
||
<span class="kn">import</span> <span class="nn">hashlib</span>
|
||
|
||
<span class="n">data</span> <span class="o">=</span> <span class="p">[</span>
|
||
<span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="s2">&quot;b7dded96-8df0-8af8-449a-8bc47f71b4c4&quot;</span><span class="p">,</span>
|
||
<span class="s2">&quot;fingerprint&quot;</span><span class="p">:</span> <span class="s2">&quot;11:D5:D2:0A:9A:F8:D9:FC:23:6E:5C:5C:30:EC:AF:68:F5:68:FB:A3&quot;</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="s2">&quot;dded96b7-8f0d-8f8a-49a4-7f771b4c4bc4&quot;</span><span class="p">,</span>
|
||
<span class="s2">&quot;fingerprint&quot;</span><span class="p">:</span> <span class="s2">&quot;33:6E:5C:5C:30:EC:AF:68:F5:68:FB:A3:11:D5:D2:0A:9A:F8:D9:FC&quot;</span><span class="p">}]</span>
|
||
|
||
<span class="n">m</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha256</span><span class="p">()</span>
|
||
<span class="n">m</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">sort_keys</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
|
||
<span class="n">collection_hash</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
</content><category term="code"></category></entry><entry><title>Let’s Encrypt + HAProxy</title><link href="https://blog.notmyidea.org/lets-encrypt-haproxy.html" rel="alternate"></link><published>2016-02-11T00:00:00+01:00</published><updated>2016-02-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-02-11:/lets-encrypt-haproxy.html</id><summary type="html"><p><em>Note : Cet article n&#8217;est plus à jour. Il est maintenant (2018) possible d&#8217;installer des certificats <span class="caps">SSL</span> Let&#8217;s Encrypt d&#8217;une manière beaucoup plus simple, en utilisant certbot (et le plugin nginx <code>certbot --nginx</code>).</em></p>
|
||
<blockquote>
|
||
<p>It’s time for the Web to take a big step forward in terms …</p></blockquote></summary><content type="html"><p><em>Note : Cet article n&#8217;est plus à jour. Il est maintenant (2018) possible d&#8217;installer des certificats <span class="caps">SSL</span> Let&#8217;s Encrypt d&#8217;une manière beaucoup plus simple, en utilisant certbot (et le plugin nginx <code>certbot --nginx</code>).</em></p>
|
||
<blockquote>
|
||
<p>It’s time for the Web to take a big step forward in terms of security
|
||
and privacy. We want to see <span class="caps">HTTPS</span> become the default. Let’s Encrypt
|
||
was built to enable that by making it as easy as possible to get and
|
||
manage&nbsp;certificates.</p>
|
||
<p>&#8212; <a href="https://letsencrypt.org/">Let&#8217;s&nbsp;Encrypt</a></p>
|
||
</blockquote>
|
||
<p>Depuis début Décembre, la nouvelle <em>autorité de certification</em> Let&#8217;s
|
||
Encrypt est passée en version <em>Beta</em>. Les certificats <span class="caps">SSL</span> sont un moyen
|
||
de 1. chiffrer la communication entre votre navigateur et le serveur et
|
||
2. un moyen d&#8217;être sur que le site Web auquel vous accédez est celui
|
||
auquel vous pensez vous connecter (pour éviter des <a href="https://fr.wikipedia.org/wiki/Attaque_de_l'homme_du_milieu">attaques de l&#8217;homme
|
||
du milieu</a>).</p>
|
||
<p>Jusqu&#8217;à maintenant, il était nécessaire de payer une entreprise pour
|
||
faire en sorte d&#8217;avoir des certificats qui évitent d&#8217;avoir ce genre
|
||
d&#8217;erreurs dans vos&nbsp;navigateurs:</p>
|
||
<p><img alt="Message de firefox lorsque une connexion n'est pas
|
||
sécurisée." src="%7Bfilename%7D/static/unsecure-connection.png"></p>
|
||
<p>Maintenant, grâce à Let&#8217;s Encrypt il est possible d&#8217;avoir des
|
||
certificats <span class="caps">SSL</span> <strong>gratuits</strong>, ce qui représente un grand pas en avant
|
||
pour la sécurité de nos&nbsp;communications.</p>
|
||
<p>Je viens de mettre en place un procédé (assez simple) qui permet de
|
||
configurer votre serveur pour générer des certificats <span class="caps">SSL</span> valides avec
|
||
Let&#8217;s Encrypt et le répartiteur de charge
|
||
<a href="http://www.haproxy.org/">HAProxy</a>.</p>
|
||
<p>Je me suis basé pour cet article sur
|
||
d&#8217;<a href="https://blog.infomee.fr/p/letsencrypt-haproxy">autres</a>
|
||
<a href="http://blog.victor-hery.com/article22/utiliser-let-s-encrypt-avec-haproxy">articles</a>,
|
||
dont je vous recommande la lecture pour un complément&nbsp;d&#8217;information.</p>
|
||
<h2 id="validation-des-domaines-par-lets-encrypt">Validation des domaines par Let&#8217;s&nbsp;Encrypt</h2>
|
||
<p>Je vous passe les détails d&#8217;installation du client de Let&#8217;s Encrypt, qui
|
||
sont <a href="https://github.com/letsencrypt/letsencrypt#installation">très bien expliqués sur leur
|
||
documentation</a>.</p>
|
||
<p>Une fois installé, vous allez taper une commande qui va ressembler&nbsp;à:</p>
|
||
<div class="highlight"><pre><span></span><code>letsencrypt-auto certonly --renew-by-default
|
||
--webroot -w /home/www/letsencrypt-requests/ \
|
||
-d hurl.kinto-storage.org \
|
||
-d forums.kinto-storage.org
|
||
</code></pre></div>
|
||
|
||
<p>Le <em>webroot</em> est l&#8217;endroit ou les preuves de détention du domaine vont
|
||
être&nbsp;déposées.</p>
|
||
<p>Lorsque les serveurs de Let&#8217;s Encrypt vont vouloir vérifier que vous
|
||
êtes bien à l&#8217;origine des demandes de certificats, ils vont envoyer une
|
||
requête <span class="caps">HTTP</span> sur <code>http://domaine.org/.well-known/acme-challenge</code>, ou il
|
||
voudra trouver des informations qu&#8217;il aura généré via la commande
|
||
<code>letsencrypt-auto</code>.</p>
|
||
<p>J&#8217;ai choisi de faire une règle dans haproxy pour diriger toutes les
|
||
requêtes avec le chemin <code>.well-known/acme-challenge</code> vers un <em>backend</em>
|
||
nginx qui sert des fichiers statiques (ceux contenus dans
|
||
<code>/home/www/letsencrypt-requests/</code>).</p>
|
||
<p>Voici la section de la configuration de HAProxy (et <a href="https://github.com/almet/infra/blob/master/haproxy/haproxy.cfg#L63-L72">la configuration
|
||
complete</a>
|
||
si ça peut être&nbsp;utile):</p>
|
||
<div class="highlight"><pre><span></span><code>frontend http
|
||
bind 0.0.0.0:80
|
||
mode http
|
||
default_backend nginx_server
|
||
|
||
acl letsencrypt_check path_beg /.well-known/acme-challenge
|
||
use_backend letsencrypt_backend if letsencrypt_check
|
||
|
||
redirect scheme https code 301 if !{ ssl_fc } !letsencrypt_check
|
||
|
||
backend letsencrypt_backend
|
||
http-request set-header Host letsencrypt.requests
|
||
dispatch 127.0.0.1:8000
|
||
</code></pre></div>
|
||
|
||
<p>Et celle de <span class="caps">NGINX</span>:</p>
|
||
<div class="highlight"><pre><span></span><code>server {
|
||
listen 8000;
|
||
server_name letsencrypt.requests;
|
||
root /home/www/letsencrypt-requests;
|
||
}
|
||
</code></pre></div>
|
||
|
||
<h2 id="installation-des-certificats-dans-haproxy">Installation des certificats dans&nbsp;HAProxy</h2>
|
||
<p>Vos certificats <span class="caps">SSL</span> devraient être générés dans <code>/etc/letsencrypt/live</code>,
|
||
mais ils ne sont pas au format attendu par haproxy. Rien de grave, la
|
||
commande suivant convertit l&#8217;ensemble des certificats en une version
|
||
compatible avec&nbsp;HAProxy:</p>
|
||
<div class="highlight"><pre><span></span><code>cat /etc/letsencrypt/live/domaine.org/privkey.pem /etc/letsencrypt/live/domaine.org/fullchain.pem &gt; /etc/ssl/letsencrypt/domaine.org.pem
|
||
</code></pre></div>
|
||
|
||
<p>Et ensuite dans la configuration de haproxy, pour le (nouveau)
|
||
<em>frontend</em>&nbsp;https:</p>
|
||
<div class="highlight"><pre><span></span><code>bind 0.0.0.0:443 ssl no-sslv3 crt /etc/ssl/letsencrypt
|
||
</code></pre></div>
|
||
|
||
<p>Faites bien attention à avoir un <em>frontend</em> https pour tous vos sites en
|
||
<span class="caps">HTTPS</span>. <a href="https://github.com/almet/infra/blob/master/haproxy/haproxy.cfg#L38-L60">Pour moi cela ressemble à
|
||
ça</a>.</p>
|
||
<p>Une fois tout ceci fait, redémarrez votre service haproxy et zou&nbsp;!</p>
|
||
<h2 id="automatisation">Automatisation</h2>
|
||
<p>Pour automatiser un peu tout ça, j&#8217;ai choisi de faire ça comme&nbsp;suit:</p>
|
||
<ul>
|
||
<li>Un fichier domaine dans <code>letsencrypt/domains/domain.org</code> qui
|
||
contient le script <code>letsencrypt</code>.</li>
|
||
<li>Un fichier d&#8217;installation de certificats dans
|
||
<code>letsencrypt/install-certs.sh</code> qui s&#8217;occupe d&#8217;installer les
|
||
certificats déjà&nbsp;générés.</li>
|
||
</ul>
|
||
<p>Et voila ! <a href="https://github.com/almet/infra/">Le tout est dans un dépot
|
||
github</a>, si jamais ça peut vous servir,
|
||
tant mieux&nbsp;!</p></content><category term="code"></category></entry><entry><title>Ateliers d’autodéfense numérique</title><link href="https://blog.notmyidea.org/ateliers-dautodefense-numerique.html" rel="alternate"></link><published>2016-01-14T00:00:00+01:00</published><updated>2016-01-14T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2016-01-14:/ateliers-dautodefense-numerique.html</id><summary type="html"><p>Il y a huit mois, je me rendais compte de l&#8217;importance du choix des
|
||
outils pour faire face à la surveillance généralisée, et notamment en
|
||
rapport au chiffrement des données. Une de mes envies de l&#8217;époque était
|
||
l&#8217;animation&nbsp;d&#8217;ateliers.</p>
|
||
<blockquote>
|
||
<p>Je compte&nbsp;donc:</p>
|
||
<ul>
|
||
<li>Organiser des ateliers de …</li></ul></blockquote></summary><content type="html"><p>Il y a huit mois, je me rendais compte de l&#8217;importance du choix des
|
||
outils pour faire face à la surveillance généralisée, et notamment en
|
||
rapport au chiffrement des données. Une de mes envies de l&#8217;époque était
|
||
l&#8217;animation&nbsp;d&#8217;ateliers.</p>
|
||
<blockquote>
|
||
<p>Je compte&nbsp;donc:</p>
|
||
<ul>
|
||
<li>Organiser des ateliers de sensibilisation aux outils de
|
||
communication, envers mes&nbsp;proches;</li>
|
||
<li>Utiliser la communication chiffrée le plus souvent possible, au
|
||
moins pour rendre le déchiffrement des messages plus longue,
|
||
&#8220;noyer le&nbsp;poisson&#8221;.</li>
|
||
</ul>
|
||
<p>&#8212; <a href="http://blog.notmyidea.org/chiffrement.html">Chiffrement</a></p>
|
||
</blockquote>
|
||
<p>J&#8217;ai mis un peu de temps à mettre le pied à l&#8217;étrier, mais je ressors
|
||
finalement du premier atelier que j&#8217;ai co-animé avec geb, auprès d&#8217;un
|
||
public de&nbsp;journalistes.</p>
|
||
<p>Pour cette première édition l&#8217;idée était à la fois d&#8217;aller à la
|
||
rencontre d&#8217;un public que je connais mal, de leur donner des outils pour
|
||
solutionner les problèmes auxquels ils font parfois face, et de me faire
|
||
une idée de ce que pouvait être un atelier sur l&#8217;autodéfense&nbsp;numérique.</p>
|
||
<p>L&#8217;objectif pour ce premier atelier était&nbsp;de:</p>
|
||
<ol>
|
||
<li>Échanger autour des besoins et <strong>faire ressortir des histoires</strong> ou
|
||
le manque d&#8217;outillage / connaissances à posé problème, dans des
|
||
situations&nbsp;concrètes;</li>
|
||
<li>Se rendre compte des &#8220;conduites à risque&#8221;, <strong>faire peur</strong> aux
|
||
personnes formées pour qu&#8217;elles se rendent compte de l&#8217;état actuel
|
||
des&nbsp;choses;</li>
|
||
<li><strong>Proposer des solutions concrètes</strong> aux problèmes soulevés, ainsi
|
||
que le minimum de connaissance théorique pour les&nbsp;appréhender.</li>
|
||
</ol>
|
||
<h2 id="1-faire-ressortir-les-problemes">1. Faire ressortir les&nbsp;problèmes</h2>
|
||
<p>Afin de faire ressortir les problèmes, nous avons choisi de constituer
|
||
des petits groupes de discussion, afin de faire des &#8220;Groupes d&#8217;Interview
|
||
Mutuels&#8221;, ou &#8220;<span class="caps">GIM</span>&#8221;:</p>
|
||
<blockquote>
|
||
<p>l’animateur invite les participants à se regrouper par trois, avec des
|
||
personnes qu’on connaît moins puis invite chacun à livrer une
|
||
expérience vécue en lien avec le thème de la réunion et les deux
|
||
autres à poser des questions leur permettant de bien saisir ce qui a
|
||
été&nbsp;vécu.</p>
|
||
<p>&#8212; «<a href="http://www.scoplepave.org/pour-s-ecouter">Pour s&#8217;écouter</a>», <span class="caps">SCOP</span>
|
||
Le&nbsp;Pavé.</p>
|
||
</blockquote>
|
||
<p>De ces <em>GIMs</em> nous avons pu ressortir quelques histoires, gravitant
|
||
autour&nbsp;de:</p>
|
||
<ul>
|
||
<li><strong>La protection des sources (d&#8217;information)</strong>: Comment faire pour
|
||
aider quelqu&#8217;un à faire &#8220;fuiter&#8221; des données depuis l&#8217;intérieur
|
||
d&#8217;une entreprise&nbsp;?</li>
|
||
<li><strong>Le chiffrement de ses données</strong>: Comment éviter de faire &#8220;fuiter&#8221;
|
||
des données importantes lors d&#8217;une perquisition de matériel&nbsp;?</li>
|
||
</ul>
|
||
<h2 id="2-faire-peur">2. Faire&nbsp;peur</h2>
|
||
<p>Un des premiers objectifs est de faire peur, afin que tout le monde se
|
||
rende compte à quel point il est facile d&#8217;accéder à certaines données.
|
||
<a href="http://blog.barbayellow.com/">Grégoire</a> m&#8217;avait conseillé quelques
|
||
petites accroches qui ont ma foi bien&nbsp;marché:</p>
|
||
<p>J&#8217;ai demandé aux présent.e.s&nbsp;de:</p>
|
||
<ul>
|
||
<li>donner leur mot de passe à voix haute devant les autres: a priori
|
||
personne ne le&nbsp;fera;</li>
|
||
<li>venir se connecter à leur compte email depuis mon ordinateur. J&#8217;ai
|
||
piégé une personne, qui est venu pour taper son mot de&nbsp;passe.</li>
|
||
</ul>
|
||
<p>Cela à été un bon moyen de parler de l&#8217;importance des traces que l&#8217;on
|
||
peut laisser sur un ordinateur, et de la confiance qu&#8217;il faut avoir dans
|
||
le matériel que l&#8217;on utilise, à fortiori si ce ne sont pas les&nbsp;vôtres.</p>
|
||
<p>Pour continuer à leur faire peur, après une brève explication de ce
|
||
qu&#8217;est <span class="caps">SSL</span> nous avons montré comment il était facile de scruter le
|
||
réseau à la recherche de mots de passe en&nbsp;clair.</p>
|
||
<h2 id="3-proposer-des-solutions-concretes">3. Proposer des solutions&nbsp;concrêtes</h2>
|
||
<p>Une fois que tout le monde avait pleinement pris sonscience des
|
||
problématiques et n&#8217;osait plus utiliser son ordinateur ou son
|
||
téléphone, on à commencé à parler de quelques solutions. Plusieurs
|
||
approches étaient possibles ici, nous avons choisi de présenter quelques
|
||
outils qui nous semblaient répondre aux&nbsp;attentes:</p>
|
||
<ul>
|
||
<li>On a expliqué ce qu&#8217;était <a href="https://tails.boum.org">Tails</a>, et
|
||
comment l&#8217;utiliser et le&nbsp;dupliquer.</li>
|
||
<li>On a pu faire un tour des outils existants sur Tails, notamment
|
||
autour de l&#8217;<em>anonymisation</em> de fichiers et la suppression effective
|
||
de&nbsp;contenus.</li>
|
||
<li>Certaines personnes ont pu créer une clé tails avec la persistance
|
||
de&nbsp;configurée.</li>
|
||
<li>Nous nous sommes connectés au réseau
|
||
<a href="https://www.torproject.org">Tor</a> et testé que nos adresses <span class="caps">IP</span>
|
||
changeaient bien à la&nbsp;demande.</li>
|
||
<li>Nous avons utilisé <a href="https://crypto.cat">CryptoCat</a> par dessus Tor,
|
||
afin de voir comment avoir une conversation confidentielle dans
|
||
laquelle il est possible d&#8217;échanger des&nbsp;fichiers.</li>
|
||
</ul>
|
||
<h2 id="retours">Retours</h2>
|
||
<p>D&#8217;une manière générale, pour une formation de trois heures et demi, je
|
||
suis assez content de l&#8217;exercice, et de l&#8217;ensemble des sujets que nous
|
||
avons pu couvrir. Il y a beaucoup de place pour l&#8217;amélioration,
|
||
notamment en amont (j&#8217;avais par exemple oublié d&#8217;amener avec moi
|
||
suffisamment de clés <span class="caps">USB</span> pour utiliser&nbsp;Tails).</p>
|
||
<p>La plupart des retours qu&#8217;on a pu avoir jusqu&#8217;à maintenant sont
|
||
positifs, et il y a l&#8217;envie d&#8217;aller plus loin sur l&#8217;ensemble de ces&nbsp;sujets.</p>
|
||
<h2 id="la-suite">La&nbsp;suite</h2>
|
||
<p>Il y a beaucoup de sujets que nous n&#8217;avons pas abordés, ou uniquement
|
||
survolés, à cause du manque de temps disponible. Idéalement, il faudrait
|
||
au moins une journée entière pour couvrir quelques sujets plus en détail
|
||
(on peut imaginer avoir une partie théorique le matin et une partie
|
||
pratique l&#8217;après-midi par&nbsp;exemple).</p>
|
||
<p>J&#8217;ai choisi volontairement de ne pas aborder le chiffrement des messages
|
||
via <span class="caps">PGP</span> parce que <a href="%7Bfilename%7D2015.05.pgp-problemes.rst">je pense que la protection que ce média propose n&#8217;est
|
||
pas suffisante</a>, mais je suis
|
||
en train de revenir sur ma décision: il pourrait être utile de présenter
|
||
l&#8217;outil, à minima, en insistant sur certaines de ses&nbsp;faiblesses.</p>
|
||
<p>Un compte twitter à été créé recemment autour des crypto-party à Rennes,
|
||
si vous êtes interessés, <a href="https://twitter.com/CryptoPartyRNS">allez jeter un coup
|
||
d&#8217;œil</a>!</p>
|
||
<p>Je n&#8217;ai pas trouvé de ressources disponibles par rapport à des plans de
|
||
formation sur le sujet, j&#8217;ai donc décidé de publier les nôtres, afin de
|
||
co-construire avec d&#8217;autres des plans de&nbsp;formation.</p>
|
||
<p>Ils sont pour l&#8217;instant disponibles <a href="http://autodefense-numerique.readthedocs.org/en/latest/">sur Read The
|
||
Docs</a>. Tous les
|
||
retours sont évidemment les bienvenus&nbsp;!</p></content><category term="code"></category></entry><entry><title>Le mail doit-il mourir ?</title><link href="https://blog.notmyidea.org/le-mail-doit-il-mourir.html" rel="alternate"></link><published>2015-11-24T00:00:00+01:00</published><updated>2015-11-24T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-11-24:/le-mail-doit-il-mourir.html</id><summary type="html"><p>J&#8217;utilise quotidiennement le protocole email, tant bien que mal, tout en sachant que l&#8217;ensemble de mes messages passent en clair sur le réseau pour la plupart de mes conversations, puisque trop peu de monde utilise le chiffrement des&nbsp;messages.</p>
|
||
<p>Et même si j&#8217;arrive à convaincre certains de …</p></summary><content type="html"><p>J&#8217;utilise quotidiennement le protocole email, tant bien que mal, tout en sachant que l&#8217;ensemble de mes messages passent en clair sur le réseau pour la plupart de mes conversations, puisque trop peu de monde utilise le chiffrement des&nbsp;messages.</p>
|
||
<p>Et même si j&#8217;arrive à convaincre certains de mes proches à installer <span class="caps">PGP</span>, je ne suis pas satisfait du résultat: les méta-données (qui contacte qui à quel
|
||
moment, et pour lui dire quoi) transitent de toute manière, elles, en clair, à la vue de&nbsp;tous.</p>
|
||
<p>Ce problème est lié directement au protocole email: il est <em>necessaire</em> de faire fuiter ces meta-données (au moins le destinataire) pour avoir un protocole
|
||
mail&nbsp;fonctionnel.</p>
|
||
<p>Le mail répond à un besoin de communication asynchrone qui permet des conversations plus réfléchies qu&#8217;un simple chat (miaou). Il est tout à fait possible d&#8217;utiliser certaines technologies existantes afin de construire le futur de l&#8217;email, pour&nbsp;lequel:</p>
|
||
<ul>
|
||
<li>Les méta-données seraient chiffrées — Il n&#8217;est pas possible de savoir qui
|
||
communique avec qui, et&nbsp;quand;</li>
|
||
<li>Le chiffrement serait fort (et protégé d&#8217;une phrase de passe&nbsp;?);</li>
|
||
<li>La fuite d&#8217;une clé de chiffrement utilisée dans un échange ne permette pas de
|
||
déchiffrer l&#8217;ensemble des échanges (forward&nbsp;secrecy);</li>
|
||
<li>Il ne soit pas possible de réutiliser les données comme preuve pour
|
||
incriminer l&#8217;emmeteur du message&nbsp;(deniability);</li>
|
||
</ul>
|
||
<p>Avec au moins ces besoins en tête, il semble qu&#8217;une revue de l&#8217;ensemble des projets existants pointe du doigt vers <a href="https://github.com/agl/pond">pond</a>, ou vers <a href="https://www.whispersystems.org">Signal</a>.</p>
|
||
<p>Malheureusement, Pond est le projet d&#8217;une seule personne, qui veut plutôt utiliser ce code comme démonstration du concept en&nbsp;question.</p></content><category term="code"></category></entry><entry><title>Web distribution signing</title><link href="https://blog.notmyidea.org/web-distribution-signing.html" rel="alternate"></link><published>2015-10-12T00:00:00+02:00</published><updated>2015-10-12T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-10-12:/web-distribution-signing.html</id><summary type="html"><p><em>I&#8217;m not a crypto expert, nor pretend to be one. These are thoughts I
|
||
want to share with the crypto community to actually see if any solution
|
||
exists to solve this particular&nbsp;problem.</em></p>
|
||
<p>One <a href="http://www.tonyarcieri.com/whats-wrong-with-webcrypto">often pointed</a> flaw in
|
||
web-based cryptographic applications is the fact that there is no way …</p></summary><content type="html"><p><em>I&#8217;m not a crypto expert, nor pretend to be one. These are thoughts I
|
||
want to share with the crypto community to actually see if any solution
|
||
exists to solve this particular&nbsp;problem.</em></p>
|
||
<p>One <a href="http://www.tonyarcieri.com/whats-wrong-with-webcrypto">often pointed</a> flaw in
|
||
web-based cryptographic applications is the fact that there is no way to
|
||
trust online software distributions. Put differently, you don&#8217;t actually
|
||
trust the software authors but are rather trusting the software
|
||
distributors and certificate authorities&nbsp;(CAs).</p>
|
||
<p>I&#8217;ve been talking with a few folks in the past months about that and
|
||
they suggested me to publish something to discuss the matter. So here I&nbsp;come!</p>
|
||
<h2 id="the-problem-attack-vectors">The problem (Attack&nbsp;vectors)</h2>
|
||
<p>Let&#8217;s try to describe a few potential&nbsp;attacks:</p>
|
||
<p><em>Application Authors</em> just released a new version of their open source
|
||
web crypto messaging application. An <em>Indie Hoster</em> installs it on their
|
||
servers so a wide audience can actually use&nbsp;it.</p>
|
||
<p>Someone alters the files on <em>Indie Hoster</em> servers, effectively
|
||
replacing them with other <em>altered files</em> with less security properties
|
||
/ a backdoor. This someone could either be an <em>Evil Attacker</em> which
|
||
found its way trough, the <em>Indie Hoster</em> or a <span class="caps">CDN</span> which delivers the&nbsp;files,</p>
|
||
<p>Trusted <em>Certificate Authorities</em> (&#8220;governments&#8221; or &#8220;hacking team&#8221;) can
|
||
also trick the User Agents (i.e. Firefox) into thinking they&#8217;re talking
|
||
to <em>Indie Hoster</em> even though they&#8217;re actually talking to a different&nbsp;server.</p>
|
||
<p><strong>Altered files</strong> are then being served to the User Agents, and <em>Evil
|
||
Attacker</em> now has a way to actually attack the end&nbsp;users.</p>
|
||
<h2 id="problem-mitigation">Problem&nbsp;Mitigation</h2>
|
||
<p>Part of the problem is solved by the recently introduced <a href="https://w3c.github.io/webappsec/specs/subresourceintegrity/">Sub Resource
|
||
Integrity</a>
|
||
(<span class="caps">SRI</span>). To quote them: &#8220;[it] defines a mechanism by which user agents
|
||
may verify that a fetched resource has been delivered without unexpected&nbsp;manipulation.&#8221;.</p>
|
||
<p><span class="caps">SRI</span> is a good start, but isn&#8217;t enough: it ensures the assets (JavaScript
|
||
files, mainly) loaded from a specific <span class="caps">HTML</span> page are the ones the author
|
||
of the <span class="caps">HTML</span> page intends. However, <span class="caps">SRI</span> doesn&#8217;t allow the User Agent to
|
||
ensure the <span class="caps">HTML</span> page is the one he&nbsp;wants.</p>
|
||
<p>In other words, we miss a way to create trust between <em>Application
|
||
Authors</em> and <em>User Agents</em>. The User-Agent currently has to trust the
|
||
<em>Certificate Authorities</em> and the delivery (<em>Indie Hoster</em>).</p>
|
||
<p>For desktop software distribution: <em>Crypto Experts</em> audit the software,
|
||
sign it somehow and then this signature can be checked locally during
|
||
installation or runtime. It&#8217;s not automated, but at least it&#8217;s&nbsp;possible.</p>
|
||
<p>For web applications, we don&#8217;t have such a mechanism, but it should be
|
||
possible. Consider the&nbsp;following:</p>
|
||
<ul>
|
||
<li><em>App Authors</em> publish a new version of their software; They provide
|
||
a hash of each of their distributed files (including the <span class="caps">HTML</span>&nbsp;files);</li>
|
||
<li><em>Crypto Experts</em> audit these files and sign the hashes&nbsp;somehow;</li>
|
||
<li><em>User Agents</em> can chose to trust some specific <em>Crypto Experts</em>;</li>
|
||
<li>When a <em>User Agent</em> downloads files, it checks if they&#8217;re signed by
|
||
a trusted&nbsp;party.</li>
|
||
</ul>
|
||
<h2 id="chosing-who-you-trust">Chosing who you&nbsp;trust</h2>
|
||
<p>In terms of user experience, handling certificates is hard, and that&#8217;s
|
||
where the community matters. Distributions such as
|
||
<a href="https://tails.boom.org">Tails</a> could chose who they trust to verify the
|
||
files, and issue warnings / refuse to run the application in case files
|
||
aren&#8217;t&nbsp;verified.</p>
|
||
<p>But, as highligted earlier, CAs are hard to trust. A new instance of the
|
||
same <span class="caps">CA</span> system wouldn&#8217;t make that much differences, expect the fact that
|
||
distributions could ship with a set of trusted authorities (for which
|
||
revocation would still need to be taken care&nbsp;of).</p>
|
||
<blockquote>
|
||
<p>[&#8230;] users are vulnerable to MitM attacks by the authority, which
|
||
can vouch for, or be coerced to vouch for, false keys. This weakness
|
||
has been highlighted by recent <span class="caps">CA</span> scandals. Both schemes can also be
|
||
attacked if the authority does not verify keys before vouching for&nbsp;them.</p>
|
||
<p>&#8212; <a href="http://cacr.uwaterloo.ca/techreports/2015/cacr2015-02.pdf">SoK : Secure
|
||
Messaging</a>;</p>
|
||
</blockquote>
|
||
<p>It seems that some other systems could allow for something more&nbsp;reliable:</p>
|
||
<blockquote>
|
||
<p>Melara et al proposed <span class="caps">CONIKS</span>, using a series of chained commitments to
|
||
Merkle prefix trees to build a key directory [&#8230;] for which
|
||
individual users can efficiently verify the consistency of their own
|
||
entry in the directory without relying on a third&nbsp;party.</p>
|
||
<p>This “self- auditing log” approach makes the system partially have no
|
||
auditing required (as general auditing of non-equivocation is still
|
||
required) and also enables the system to be privacy preserving as the
|
||
entries in the directory need not be made public. This comes at a mild
|
||
bandwidth cost not reflected in our table, estimated to be about 10
|
||
kilobytes per client per day for&nbsp;self-auditing.</p>
|
||
<p>&#8212; <a href="http://cacr.uwaterloo.ca/techreports/2015/cacr2015-02.pdf">SoK : Secure
|
||
Messaging</a>;</p>
|
||
</blockquote>
|
||
<p>Now, I honestly have no idea if this thing solves the whole problem, and
|
||
I&#8217;m pretty sure this design has many security problems attached to&nbsp;it.</p>
|
||
<p>However, that&#8217;s a problem I would really like to see solved one day, so
|
||
here the start of the discussion, don&#8217;t hesitate to <a href="/pages/about.html">get in
|
||
touch</a>!</p>
|
||
<h2 id="addendum">Addendum</h2>
|
||
<p>It seems possible to increase the level a user has in a Web Application
|
||
by adding indicators in the User-Agent. For instance, when using an
|
||
application that&#8217;s actually signed by someone considered trustful by the
|
||
User-Agent (or the distributor of the User-Agent), a little green icon
|
||
could be presented to the User, so they know that they can be confident
|
||
about&nbsp;this.</p>
|
||
<p>A bit like User-Agents do for <span class="caps">SSL</span>, but for the actual signature of the
|
||
files being&nbsp;viewed.</p></content><category term="code"></category></entry><entry><title>Service de nuages : Pourquoi avons-nous fait Cliquet ?</title><link href="https://blog.notmyidea.org/pourquoi-cliquet" rel="alternate"></link><published>2015-07-14T00:00:00+02:00</published><updated>2015-07-14T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-07-14:/pourquoi-cliquet</id><summary type="html"><p class="first last">Basé sur Pyramid, Cliquet est un projet qui permet de se concentrer sur l&#8217;essentiel
|
||
lors de la conception&nbsp;d&#8217;APIs.</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p><strong>tldr; Cliquet est un toolkit Python pour construire des APIs, qui implémente
|
||
les bonnes pratiques en terme de mise en production et de protocole <span class="caps">HTTP</span>.</strong></p>
|
||
<div class="section" id="les-origines">
|
||
<h2>Les&nbsp;origines</h2>
|
||
<p>L&#8217;objectif pour le premier trimestre 2015 était de construire un service de
|
||
stockage et de <a class="reference external" href="https://blog.notmyidea.org/service-de-nuages-fr.html">synchronisation de listes de lecture</a>.</p>
|
||
<p>Au démarrage du projet, nous avons tenté de rassembler toutes les bonnes pratiques
|
||
et recommandations, venant de différentes équipes et surtout des derniers projets&nbsp;déployés.</p>
|
||
<p>De même, nous voulions tirer parti du protocole de <em>Firefox Sync</em>, robuste et éprouvé,
|
||
pour la synchronisation des données&nbsp;«offline».</p>
|
||
<p>Plutôt qu&#8217;écrire un <a class="reference external" href="http://blog.octo.com/en/design-a-rest-api/">énième</a>
|
||
<a class="reference external" href="http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api">article</a> de blog,
|
||
nous avons préféré les rassembler dans ce qu&#8217;on a appellé «un&nbsp;protocole».</p>
|
||
<p>Comme pour l&#8217;architecture envisagée nous avions deux projets à construire, qui
|
||
devaient obéir globalement à ces mêmes règles, nous avons décidé de mettre en
|
||
commun l&#8217;implémentation de ce protocole et de ces bonnes pratiques dans un&nbsp;«toolkit».</p>
|
||
<p><em>Cliquet</em> est&nbsp;né.</p>
|
||
<img alt="Cliquet logo" class="align-center" src="https://blog.notmyidea.org/images/cliquet/cliquet-logo.png" />
|
||
<div class="section" id="les-intentions">
|
||
<h3>Les&nbsp;intentions</h3>
|
||
<blockquote class="epigraph">
|
||
Quelle structure <span class="caps">JSON</span> pour mon <span class="caps">API</span> ? Quelle syntaxe pour filtrer la liste
|
||
via la querystring ? Comment gérer les écritures concurrentes ?
|
||
Et synchroniser les données dans mon application cliente ?</blockquote>
|
||
<p>Désormais, quand un projet souhaite bénéficier d&#8217;une <span class="caps">API</span> <span class="caps">REST</span> pour stocker et consommer
|
||
des données, il est possible d&#8217;utiliser le <strong>protocole <span class="caps">HTTP</span></strong> proposé
|
||
et de se concentrer sur l&#8217;essentiel. Cela vaut aussi pour les clients, où
|
||
la majorité du code d&#8217;interaction avec le serveur est&nbsp;réutilisable.</p>
|
||
<blockquote class="epigraph">
|
||
Comment pouvons-nous vérifier que le service est opérationnel ? Quels indicateurs StatsD ?
|
||
Est-ce que Sentry est bien configuré ? Comment déployer une nouvelle version
|
||
sans casser les applications clientes ?</blockquote>
|
||
<p>Comme <em>Cliquet</em> fournit tout ce qui est nécessaire pour être conforme avec les
|
||
exigences de la <strong>mise en production</strong>, le passage du prototype au service opérationnel
|
||
est très rapide ! De base le service répondra aux attentes en terme supervision, configuration,
|
||
déploiement et dépréciation de version. Et si celles-ci évoluent, il suffira
|
||
de faire évoluer le&nbsp;toolkit.</p>
|
||
<blockquote class="epigraph">
|
||
Quel backend de stockage pour des documents <span class="caps">JSON</span> ? Comment faire si l&#8217;équipe
|
||
de production impose PostgreSQL ? Et si on voulait passer à Redis ou en
|
||
mémoire pour lancer les tests ?</blockquote>
|
||
<p>En terme d&#8217;implémentation, nous avons choisi de <strong>fournir des abstractions</strong>.
|
||
En effet, nous avions deux services dont le coeur consistait
|
||
à exposer un <em><span class="caps">CRUD</span></em> en <em><span class="caps">REST</span></em>, persistant des données <span class="caps">JSON</span> dans un backend.
|
||
Comme <em>Pyramid</em> et <em>Cornice</em> ne fournissent rien de tout prêt pour ça,
|
||
nous avons voulu introduire des classes de bases pour abstraire les notions
|
||
de resource <span class="caps">REST</span> et de backend de&nbsp;stockage.</p>
|
||
<p>Dans le but de tout rendre optionnel et «pluggable», <strong>tout est configurable</strong>
|
||
depuis le fichier <tt class="docutils literal">.ini</tt> de l&#8217;application. Ainsi tous les projets qui utilisent
|
||
le toolkit se déploieront de la même manière : seuls quelques éléments de configuration
|
||
les&nbsp;distingueront.</p>
|
||
<img alt="Une réunion à Paris..." class="align-center" src="https://blog.notmyidea.org/images/cliquet/cliquet-notes-whiteboard.jpg" />
|
||
</div>
|
||
</div>
|
||
<div class="section" id="le-protocole">
|
||
<h2>Le&nbsp;protocole</h2>
|
||
<blockquote class="epigraph">
|
||
Est-ce suffisant de parler d&#8217;«<span class="caps">API</span> <span class="caps">REST</span>» ? Est-ce bien nécessaire de
|
||
relire la spec <span class="caps">HTTP</span> à chaque fois ? Pourquoi réinventer un protocole complet
|
||
à chaque fois ?</blockquote>
|
||
<p>Quand nous développons un (micro)service Web, nous dépensons généralement beaucoup
|
||
trop d&#8217;énergie à (re)faire des choix&nbsp;(arbitraires).</p>
|
||
<p>Nul besoin de lister ici tout ce qui concerne la dimension
|
||
de la spécification <span class="caps">HTTP</span> pure, qui nous impose le format des headers,
|
||
le support de <span class="caps">CORS</span>, la négocation de contenus (types mime), la différence entre
|
||
authentification et autorisation, la cohérence des code&nbsp;status&#8230;</p>
|
||
<p>Les choix principaux du protocole concernent surtout&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li><strong>Les resources <span class="caps">REST</span></strong> : Les deux URLs d&#8217;une resource (pour la collection
|
||
et les enregistrements) acceptent des verbes et des headers&nbsp;précis.</li>
|
||
<li><strong>Les formats</strong> : le format et la structure <span class="caps">JSON</span> des réponses est imposé, ainsi
|
||
que la pagination des listes ou la syntaxe pour filtrer/trier les resources via la <a class="reference external" href="https://en.wikipedia.org/wiki/Query_string">querystring</a>.</li>
|
||
<li><strong>Les timestamps</strong> : un numéro de révision qui s&#8217;incrémente à chaque opération
|
||
d&#8217;écriture sur une collection&nbsp;d&#8217;enregistrements.</li>
|
||
<li><strong>La synchronisation</strong> : une série de leviers pour récupérer et renvoyer des
|
||
changements sur les données, sans perte ni collision, en utilisant les&nbsp;timestamps.</li>
|
||
<li><strong>Les permissions</strong> : les droits d&#8217;un utilisateur sur une collection ou un enregistrement
|
||
(<em>encore frais et sur le point d&#8217;être documenté</em>) <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>.</li>
|
||
<li><strong>Opérations par lot</strong>: une <span class="caps">URL</span> qui permet d&#8217;envoyer une série de requêtes
|
||
décrites en <span class="caps">JSON</span> et d&#8217;obtenir les réponses&nbsp;respectives.</li>
|
||
</ul>
|
||
<p>Dans la dimension opérationnelle du protocole, on trouve&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li><strong>La gestion de version</strong> : cohabitation de plusieurs versions en production,
|
||
avec alertes dans les entêtes pour la fin de vie des anciennes&nbsp;versions.</li>
|
||
<li><strong>Le report des requêtes</strong> : entêtes interprétées par les clients, activées en cas de
|
||
maintenance ou de surchage, pour ménager le&nbsp;serveur.</li>
|
||
<li><strong>Le canal d&#8217;erreurs</strong> : toutes les erreurs renvoyées par le serveur ont le même
|
||
format <span class="caps">JSON</span> et ont un numéro&nbsp;précis.</li>
|
||
<li><strong>Les utilitaires</strong> : URLs diverses pour répondre aux besoins exprimés par
|
||
l&#8217;équipe d&#8217;administrateurs (monitoring, metadonnées, paramètres&nbsp;publiques).</li>
|
||
</ul>
|
||
<p>Ce protocole est une compilation des bonnes pratiques pour les APIs <span class="caps">HTTP</span> (<em>c&#8217;est notre métier !</em>),
|
||
des conseils des administrateurs système dont c&#8217;est le métier de mettre à disposition des services
|
||
pour des millions d&#8217;utilisateurs et des retours d&#8217;expérience de l&#8217;équipe
|
||
de <em>Firefox Sync</em> pour la gestion de la concurrence et de&nbsp;l&#8217;«offline-first».</p>
|
||
<p>Il est <a class="reference external" href="http://cliquet.readthedocs.org/en/latest/api/index.html">documenté en détail</a>.</p>
|
||
<p>Dans un monde idéal, ce protocole serait versionné, et formalisé dans une <span class="caps">RFC</span>.
|
||
En rêve, il existerait même plusieurs implémentations avec des codes différentes
|
||
(Python, Go, Node, etc.). <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a></p>
|
||
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>Voir notre <a class="reference external" href="https://blog.notmyidea.org/service-de-nuages-la-gestion-des-permissions-fr.html">article dédié sur les permissions</a></td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td>Rappel: nous sommes une toute petite équipe !</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="section" id="le-toolkit">
|
||
<h2>Le&nbsp;toolkit</h2>
|
||
<div class="section" id="choix-techniques">
|
||
<h3>Choix&nbsp;techniques</h3>
|
||
<p><em>Cliquet</em> implémente le protocole en Python (<em>2.7, 3.4+, pypy</em>), avec <a class="reference external" href="http://trypyramid.com/">Pyramid</a> <a class="footnote-reference" href="#footnote-3" id="footnote-reference-3">[3]</a>.</p>
|
||
<p><strong>Pyramid</strong> est un framework Web qui va prendre en charge tout la partie <span class="caps">HTTP</span>,
|
||
et qui s&#8217;avère pertinent aussi bien pour des petits projets que des plus&nbsp;ambitieux.</p>
|
||
<p><strong>Cornice</strong> est une extension de <em>Pyramid</em>, écrite en partie par Alexis et Tarek,
|
||
qui permet d&#8217;éviter d&#8217;écrire tout le code <em>boilerplate</em> quand on construit une
|
||
<span class="caps">API</span> <span class="caps">REST</span> avec&nbsp;Pyramid.</p>
|
||
<p>Avec <em>Cornice</em>, on évite de réécrire à chaque fois le code qui va
|
||
cabler les verbes <span class="caps">HTTP</span> aux méthodes, valider les entêtes, choisir le sérialiseur
|
||
en fonction des entêtes de négociation de contenus, renvoyer les codes <span class="caps">HTTP</span>
|
||
rigoureux, gérer les entêtes <span class="caps">CORS</span>, fournir la validation <span class="caps">JSON</span> à partir de&nbsp;schémas&#8230;</p>
|
||
<p><strong>Cliquet</strong> utilise les deux précédents pour implémenter le protocole et fournir
|
||
des abstractions, mais on a toujours <em>Pyramid</em> et <em>Cornice</em> sous la main pour
|
||
aller au delà de ce qui est proposé&nbsp;!</p>
|
||
<table class="docutils footnote" frame="void" id="footnote-3" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-3">[3]</a></td><td>Au tout début nous avons commencé une implémentation avec <em>Python-Eve</em>
|
||
(Flask), mais n&#8217;étions pas satisfaits de l&#8217;approche pour la configuration
|
||
de l&#8217;<span class="caps">API</span>. En particulier du côté magique.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="section" id="concepts">
|
||
<h3>Concepts</h3>
|
||
<p>Bien évidemment, les concepts du toolkit reflètent ceux du protocole mais il y
|
||
a des éléments&nbsp;supplémentaires:</p>
|
||
<ul class="simple">
|
||
<li><strong>Les backends</strong> : abstractions pour le stockage, le cache et les permissions
|
||
(<em>ex. PostgreSQL, Redis, en-mémoire, &#8230;</em>)</li>
|
||
<li><strong>La supervision</strong> : logging <span class="caps">JSON</span> et indicateurs temps-réel (<em>StatsD</em>) pour suivre les
|
||
performances et la santé du&nbsp;service.</li>
|
||
<li><strong>La configuration</strong> : chargement de la configuration depuis les variables
|
||
d&#8217;environnement et le fichier <tt class="docutils literal">.ini</tt></li>
|
||
<li><strong>La flexibilité</strong> : dés/activation ou substitution de la majorité des composants
|
||
depuis la&nbsp;configuration.</li>
|
||
<li><strong>Le profiling</strong> : utilitaires de développement pour trouver les <a class="reference external" href="https://fr.wiktionary.org/wiki/goulet_d%E2%80%99%C3%A9tranglement">goulets
|
||
d&#8217;étranglement</a>.</li>
|
||
</ul>
|
||
<img alt="Cliquet concepts" class="align-center" src="https://blog.notmyidea.org/images/cliquet/cliquet-concepts.png" />
|
||
<p>Proportionnellement, l&#8217;implémentation du protocole pour les resources <span class="caps">REST</span> est
|
||
la plus volumineuse dans le code source de <em>Cliquet</em>.
|
||
Cependant, comme nous l&#8217;avons décrit plus haut, <em>Cliquet</em> fournit tout un
|
||
ensemble d&#8217;outillage et de bonnes pratiques, et reste
|
||
donc tout à fait pertinent pour n&#8217;importe quel type d&#8217;<span class="caps">API</span>, même sans
|
||
manipulation de données&nbsp;!</p>
|
||
<p>L&#8217;objectif de la boîte à outils est de faire en sorte qu&#8217;un développeur puisse constuire
|
||
une application simplement, en étant sûr qu&#8217;elle réponde aux exigeances de la
|
||
mise en production, tout en ayant la possibilité de remplacer certaines parties
|
||
au fur et à mesure que ses besoins se&nbsp;précisent.</p>
|
||
<p>Par exemple, la persistence fournie par défault est <em>schemaless</em> (e.g <em><span class="caps">JSONB</span></em>),
|
||
mais rien n&#8217;empêcherait d&#8217;implémenter le stockage dans un modèle&nbsp;relationnel.</p>
|
||
<p>Comme les composants peuvent être remplacés depuis la configuration, il est
|
||
tout à fait possible d&#8217;étendre <em>Cliquet</em> avec des notions métiers ou des
|
||
codes exotiques ! Nous avons posé quelques idées dans <a class="reference external" href="http://cliquet.readthedocs.org/en/latest/ecosystem.html">la documentation
|
||
de l&#8217;éco-système</a>.</p>
|
||
<p>Dans les prochaines semaines, nous allons introduire la notion d&#8217;«évènements» (ou signaux),
|
||
qui permettraient aux extensions de s&#8217;interfacer beaucoup plus&nbsp;proprement.</p>
|
||
<p>Nous attachons beaucoup d&#8217;importance à la clareté du code, la pertinence des
|
||
<em>patterns</em>, des tests et de la documentation. Si vous avez des commentaires,
|
||
des critiques ou des interrogations, n&#8217;hésitez pas à <a class="reference external" href="https://github.com/mozilla-services/cliquet/issues">nous en faire part</a>&nbsp;!</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="cliquet-a-l-action">
|
||
<h2>Cliquet, à&nbsp;l&#8217;action.</h2>
|
||
<p>Nous avons écrit un <a class="reference external" href="http://cliquet.readthedocs.org/en/latest/quickstart.html">guide de démarrage</a>,
|
||
qui n&#8217;exige pas de connaître <em>Pyramid</em>.</p>
|
||
<p>Pour illustrer la simplicité et les concepts, voici quelques extraits&nbsp;!</p>
|
||
<div class="section" id="etape-1">
|
||
<h3>Étape&nbsp;1</h3>
|
||
<p>Activer <em>Cliquet</em>:</p>
|
||
<div class="highlight"><pre><span></span><span class="hll"><span class="kn">import</span> <span class="nn">cliquet</span>
|
||
</span><span class="kn">from</span> <span class="nn">pyramid.config</span> <span class="kn">import</span> <span class="n">Configurator</span>
|
||
|
||
<span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">global_config</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">):</span>
|
||
<span class="n">config</span> <span class="o">=</span> <span class="n">Configurator</span><span class="p">(</span><span class="n">settings</span><span class="o">=</span><span class="n">settings</span><span class="p">)</span>
|
||
|
||
<span class="hll"> <span class="n">cliquet</span><span class="o">.</span><span class="n">initialize</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="s1">&#39;1.0&#39;</span><span class="p">)</span>
|
||
</span> <span class="k">return</span> <span class="n">config</span><span class="o">.</span><span class="n">make_wsgi_app</span><span class="p">()</span>
|
||
</pre></div>
|
||
<p>À partir de là, la plupart des outils de <em>Cliquet</em> sont activés et&nbsp;accessibles.</p>
|
||
<p>Par exemple, les URLs <em>hello</em> (<tt class="docutils literal">/v1/</tt>) ou <em>supervision</em> (<tt class="docutils literal">/v1/__heartbeat__</tt>).
|
||
Mais aussi les backends de stockage, de cache, etc.
|
||
qu&#8217;il est possible d&#8217;utiliser dans des vues classiques <em>Pyramid</em> ou <em>Cornice</em>.</p>
|
||
</div>
|
||
<div class="section" id="etape-2">
|
||
<h3>Étape&nbsp;2</h3>
|
||
<p>Ajouter des&nbsp;vues:</p>
|
||
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">main</span><span class="p">(</span><span class="n">global_config</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">):</span>
|
||
<span class="n">config</span> <span class="o">=</span> <span class="n">Configurator</span><span class="p">(</span><span class="n">settings</span><span class="o">=</span><span class="n">settings</span><span class="p">)</span>
|
||
|
||
<span class="n">cliquet</span><span class="o">.</span><span class="n">initialize</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="s1">&#39;1.0&#39;</span><span class="p">)</span>
|
||
<span class="hll"> <span class="n">config</span><span class="o">.</span><span class="n">scan</span><span class="p">(</span><span class="s2">&quot;myproject.views&quot;</span><span class="p">)</span>
|
||
</span> <span class="k">return</span> <span class="n">config</span><span class="o">.</span><span class="n">make_wsgi_app</span><span class="p">()</span>
|
||
</pre></div>
|
||
<p>Pour définir des resources <span class="caps">CRUD</span>, il faut commencer par définir un schéma,
|
||
avec <em>Colander</em>, et ensuite déclarer une&nbsp;resource:</p>
|
||
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">cliquet</span> <span class="kn">import</span> <span class="n">resource</span><span class="p">,</span> <span class="n">schema</span>
|
||
|
||
<span class="k">class</span> <span class="nc">BookmarkSchema</span><span class="p">(</span><span class="n">schema</span><span class="o">.</span><span class="n">ResourceSchema</span><span class="p">):</span>
|
||
<span class="n">url</span> <span class="o">=</span> <span class="n">schema</span><span class="o">.</span><span class="n">URL</span><span class="p">()</span>
|
||
|
||
<span class="hll"><span class="nd">@resource</span><span class="o">.</span><span class="n">register</span><span class="p">()</span>
|
||
</span><span class="hll"><span class="k">class</span> <span class="nc">Bookmark</span><span class="p">(</span><span class="n">resource</span><span class="o">.</span><span class="n">BaseResource</span><span class="p">):</span>
|
||
</span><span class="hll"> <span class="n">mapping</span> <span class="o">=</span> <span class="n">BookmarkSchema</span><span class="p">()</span>
|
||
</span></pre></div>
|
||
<p>Désormais, la resource <span class="caps">CRUD</span> est disponible sur <tt class="docutils literal">/v1/bookmarks</tt>, avec toutes
|
||
les fonctionnalités de synchronisation, filtrage, tri, pagination, timestamp, etc.
|
||
De base les enregistrements sont privés, par&nbsp;utilisateur.</p>
|
||
<div class="highlight"><pre><span></span><span class="err">$</span><span class="w"> </span><span class="err">h</span><span class="kc">tt</span><span class="err">p</span><span class="w"> </span><span class="err">GET</span><span class="w"> </span><span class="s2">&quot;http://localhost:8000/v1/bookmarks&quot;</span>
|
||
<span class="err">HTTP/</span><span class="mf">1.1</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="err">OK</span>
|
||
<span class="err">...</span>
|
||
<span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;data&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
|
||
<span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">&quot;url&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;http://cliquet.readthedocs.org&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;cc103eb5-0c80-40ec-b6f5-dad12e7d975e&quot;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="nt">&quot;last_modified&quot;</span><span class="p">:</span><span class="w"> </span><span class="mi">1437034418940</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="w"> </span><span class="p">]</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="section" id="etape-3">
|
||
<h3>Étape&nbsp;3</h3>
|
||
<p>Évidemment, il est possible choisir les <span class="caps">URLS</span>, les verbes <span class="caps">HTTP</span> supportés, de modifier
|
||
des champs avant l&#8217;enregistrement,&nbsp;etc.</p>
|
||
<div class="highlight"><pre><span></span><span class="hll"><span class="nd">@resource</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">collection_path</span><span class="o">=</span><span class="s1">&#39;/user/bookmarks&#39;</span><span class="p">,</span>
|
||
</span><span class="hll"> <span class="n">record_path</span><span class="o">=</span><span class="s1">&#39;/user/bookmarks/{{id}}&#39;</span><span class="p">,</span>
|
||
</span><span class="hll"> <span class="n">collection_methods</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;GET&#39;</span><span class="p">,))</span>
|
||
</span><span class="k">class</span> <span class="nc">Bookmark</span><span class="p">(</span><span class="n">resource</span><span class="o">.</span><span class="n">BaseResource</span><span class="p">):</span>
|
||
<span class="n">mapping</span> <span class="o">=</span> <span class="n">BookmarkSchema</span><span class="p">()</span>
|
||
|
||
<span class="hll"> <span class="k">def</span> <span class="nf">process_record</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new</span><span class="p">,</span> <span class="n">old</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
</span><span class="hll"> <span class="k">if</span> <span class="n">old</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">new</span><span class="p">[</span><span class="s1">&#39;device&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="n">old</span><span class="p">[</span><span class="s1">&#39;device&#39;</span><span class="p">]:</span>
|
||
</span><span class="hll"> <span class="n">device</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;User-Agent&#39;</span><span class="p">)</span>
|
||
</span><span class="hll"> <span class="n">new</span><span class="p">[</span><span class="s1">&#39;device&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">device</span>
|
||
</span><span class="hll"> <span class="k">return</span> <span class="n">new</span>
|
||
</span></pre></div>
|
||
<p><a class="reference external" href="http://cliquet.readthedocs.org/en/latest/reference/resource.html">Plus d&#8217;infos dans la documentation dédiée</a>&nbsp;!</p>
|
||
<div class="admonition note">
|
||
<p class="first admonition-title">Note</p>
|
||
<p class="last">Il est possible de définir des resources sans validation de schema.
|
||
<a class="reference external" href="https://github.com/mozilla-services/kinto/blob/master/kinto/views/records.py">Voir le code source de Kinto</a>.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="etape-4-optionelle">
|
||
<h3>Étape 4&nbsp;(optionelle)</h3>
|
||
<p>Utiliser les abstractions de <em>Cliquet</em> dans une vue <em>Cornice</em>.</p>
|
||
<p>Par exemple, une vue qui utilise le backend de&nbsp;stockage:</p>
|
||
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">cliquet</span> <span class="kn">import</span> <span class="n">Service</span>
|
||
|
||
<span class="n">score</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;score&quot;</span><span class="p">,</span>
|
||
<span class="n">path</span><span class="o">=</span><span class="s1">&#39;/score/</span><span class="si">{game}</span><span class="s1">&#39;</span><span class="p">,</span>
|
||
<span class="n">description</span><span class="o">=</span><span class="s2">&quot;Store game score&quot;</span><span class="p">)</span>
|
||
|
||
<span class="nd">@score</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">schema</span><span class="o">=</span><span class="n">ScoreSchema</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">post_score</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="n">collection_id</span> <span class="o">=</span> <span class="s1">&#39;scores-&#39;</span> <span class="o">+</span> <span class="n">request</span><span class="o">.</span><span class="n">match_dict</span><span class="p">[</span><span class="s1">&#39;game&#39;</span><span class="p">]</span>
|
||
<span class="n">user_id</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">authenticated_userid</span>
|
||
<span class="n">value</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">validated</span> <span class="c1"># c.f. Cornice.</span>
|
||
|
||
<span class="hll"> <span class="n">storage</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">registry</span><span class="o">.</span><span class="n">storage</span>
|
||
</span><span class="hll"> <span class="n">record</span> <span class="o">=</span> <span class="n">storage</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">collection_id</span><span class="p">,</span> <span class="n">user_id</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
</span> <span class="k">return</span> <span class="n">record</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="vos-retours">
|
||
<h2>Vos&nbsp;retours</h2>
|
||
<p>N&#8217;hésitez pas à nous faire part de vos retours ! Cela vous a donné envie
|
||
d&#8217;essayer ? Vous connaissez un outil similaire ?
|
||
Y-a-t-il des points qui ne sont pas clairs ? Manque de cas d&#8217;utilisation concrets ?
|
||
Certains aspects mal pensés ? Trop contraignants ? Trop de magie ? Overkill&nbsp;?</p>
|
||
<p>Nous prenons&nbsp;tout.</p>
|
||
<div class="section" id="points-faibles">
|
||
<h3>Points&nbsp;faibles</h3>
|
||
<p>Nous sommes très fiers de ce que nous avons construit, en relativement peu
|
||
de temps. Et comme nous l&#8217;exposions dans l&#8217;article précédent (plus accessible), il y a du potentiel&nbsp;!</p>
|
||
<p>Cependant, nous sommes conscients d&#8217;un certain nombre de points
|
||
qui peuvent être vus comme des&nbsp;faiblesses.</p>
|
||
<ul class="simple">
|
||
<li><strong>La documentation d&#8217;<span class="caps">API</span></strong> : actuellement, nous n&#8217;avons pas de solution pour qu&#8217;un
|
||
projet qui utilise <em>Cliquet</em> puisse intégrer facilement toute
|
||
<a class="reference external" href="http://cliquet.readthedocs.org/en/latest/api/index.html">la documentation de l&#8217;<span class="caps">API</span></a>&nbsp;obtenue.</li>
|
||
<li><strong>La documentation</strong> : il est très difficile d&#8217;organiser la documentation, surtout
|
||
quand le public visé est aussi bien débutant qu&#8217;expérimenté. Nous sommes probablement
|
||
victimes du «<a class="reference external" href="https://en.wikipedia.org/wiki/Curse_of_knowledge">curse of knowledge</a>».</li>
|
||
<li><strong>Le protocole</strong> : on sent bien qu&#8217;on va devoir versionner le protocole. Au
|
||
moins pour le désolidariser des versions de <em>Cliquet</em>, si on veut aller au
|
||
bout de la philosophie et de&nbsp;l&#8217;éco-système.</li>
|
||
<li><strong>Le conservatisme</strong> : Nous aimons la stabilité et la robustesse. Mais surtout
|
||
nous ne sommes pas tout seuls et devons nous plier aux contraintes de la mise
|
||
en production ! Cependant, nous avons très envie de faire de l&#8217;async avec Python 3&nbsp;!</li>
|
||
<li><strong>Publication de versions</strong> : le revers de la médaille de la factorisation. Il
|
||
arrive qu&#8217;on préfère faire évoluer le toolkit (e.g. ajouter une option) pour
|
||
un point précis d&#8217;un projet. En conséquence, on doit souvent releaser les
|
||
projets en&nbsp;cascade.</li>
|
||
</ul>
|
||
</div>
|
||
<div class="section" id="quelques-questions-courantes">
|
||
<h3>Quelques questions&nbsp;courantes</h3>
|
||
<blockquote>
|
||
Pourquoi Python ?</blockquote>
|
||
<p>On prend beaucoup de plaisir à écrire du Python, et le calendrier annoncé
|
||
initialement était très serré: pas question de tituber avec une code
|
||
mal maitrisée&nbsp;!</p>
|
||
<p>Et puis, après avoir passé près d&#8217;un an sur un projet Node.js, l&#8217;équipe avait
|
||
bien envie de refaire du&nbsp;Python.</p>
|
||
<blockquote>
|
||
Pourquoi pas Django ?</blockquote>
|
||
<p>On y a pensé, surtout parce qu&#8217;il y a plusieurs fans de <em>Django <span class="caps">REST</span> Framework</em>
|
||
dans&nbsp;l&#8217;équipe.</p>
|
||
<p>On l&#8217;a écarté principalement au profit de la légèreté et la modularité de
|
||
<em>Pyramid</em>.</p>
|
||
<blockquote>
|
||
Pourquoi pas avec un framework asynchrone en Python 3+ ?</blockquote>
|
||
<p>Pour l&#8217;instant nos administrateurs système nous imposent des déploiements en
|
||
Python 2.7, à notre grand désarroi&nbsp;/o\</p>
|
||
<p>Pour <em>Reading List</em>, nous <a class="reference external" href="https://github.com/mozilla-services/readinglist/blob/1.7.0/readinglist/__init__.py#L19-L26">avions activé</a>
|
||
<em>gevent</em>.</p>
|
||
<p>Puisque l&#8217;approche consiste à implémenter un protocole bien déterminé, nous n&#8217;excluons
|
||
pas un jour d&#8217;écrire un <em>Cliquet</em> en <em>aiohttp</em> ou <em>Go</em> si cela s&#8217;avèrerait&nbsp;pertinent.</p>
|
||
<blockquote>
|
||
Pourquoi pas <span class="caps">JSON</span>-<span class="caps">API</span> ?</blockquote>
|
||
<p>Comme nous l&#8217;expliquions au retour des APIdays,
|
||
<span class="caps">JSON</span>-<span class="caps">API</span> est une spécification qui rejoint plusieurs de nos&nbsp;intentions.</p>
|
||
<p>Quand nous avons commencé le protocole, nous ne connaissions pas <span class="caps">JSON</span>-<span class="caps">API</span>.
|
||
Pour l&#8217;instant, comme notre proposition est beaucoup plus minimaliste, le
|
||
rapprochement n&#8217;a <a class="reference external" href="https://github.com/mozilla-services/cliquet/issues/254">pas dépassé le stade de la discussion</a>.</p>
|
||
<blockquote>
|
||
Est-ce que Cliquet est un framework <span class="caps">REST</span> pour Pyramid ?</blockquote>
|
||
<p>Non.</p>
|
||
<p>Au delà des classes de resources <span class="caps">CRUD</span> de Cliquet, qui implémentent un
|
||
protocole bien précis, il faut utiliser Cornice ou Pyramid&nbsp;directement.</p>
|
||
<blockquote>
|
||
Est-ce que Cliquet est suffisamment générique pour des projets hors Mozilla ?</blockquote>
|
||
<p>Premièrement, nous faisons en sorte que tout soit contrôlable depuis la
|
||
configuration <tt class="docutils literal">.ini</tt> pour permettre la dés/activation ou substitution des&nbsp;composants.</p>
|
||
<p>Si le protocole <span class="caps">HTTP</span>/<span class="caps">JSON</span> des resources <span class="caps">CRUD</span> vous satisfait,
|
||
alors Cliquet est probablement le plus court chemin pour construire une
|
||
application qui tient la&nbsp;route.</p>
|
||
<p>Mais l&#8217;utilisation des resources <span class="caps">CRUD</span> est facultative, donc Cliquet reste pertinent
|
||
si les bonnes pratiques en terme de mise en production ou les abstractions fournies
|
||
vous paraissent valables&nbsp;!</p>
|
||
<p>Cliquet reste un moyen simple d&#8217;aller très vite pour mettre sur pied
|
||
une application&nbsp;Pyramid/Cornice.</p>
|
||
<blockquote>
|
||
Est-ce que les resources <span class="caps">JSON</span> supporte les modèles relationnels complexes ?</blockquote>
|
||
<p>La couche de persistence fournie est très simple, et devrait
|
||
répondre à la majorité des cas d&#8217;utilisation où les données n&#8217;ont pas de&nbsp;relations.</p>
|
||
<p>En revanche, il est tout à fait possible de bénéficier de tous les aspects
|
||
du protocole en utilisant une classe <tt class="docutils literal">Collection</tt> maison, qui se chargerait
|
||
elle de manipuler les&nbsp;relations.</p>
|
||
<p>Le besoin de relations pourrait être un bon prétexte pour implémenter le
|
||
protocole avec Django <span class="caps">REST</span> Framework&nbsp;:)</p>
|
||
<blockquote>
|
||
Est-il possible de faire ci ou ça avec Cliquet ?</blockquote>
|
||
<p>Nous aimerions collecter des besoins pour écrire un ensemble de «recettes/tutoriels». Mais
|
||
pour ne pas travailler dans le vide, nous aimerions <a class="reference external" href="https://github.com/mozilla-services/cliquet/issues">connaitre vos idées</a> !
|
||
(<em>ex. brancher l&#8217;authentification Github, changer le format du logging <span class="caps">JSON</span>, stocker des
|
||
données cartographiques, &#8230;</em>)</p>
|
||
<blockquote>
|
||
Est-ce que Cliquet peut manipuler des fichiers ?</blockquote>
|
||
<p><a class="reference external" href="https://github.com/mozilla-services/cliquet/issues/236">Nous l&#8217;envisageons</a>,
|
||
mais pour l&#8217;instant nous attendons que le besoin survienne en interne pour se&nbsp;lancer.</p>
|
||
<p>Si c&#8217;est le cas, le protocole utilisé sera <a class="reference external" href="http://remotestorage.io/">Remote Storage</a>,
|
||
afin notamment de s&#8217;intégrer dans l&#8217;éco-système&nbsp;grandissant.</p>
|
||
<blockquote>
|
||
Est-ce que la fonctionnalité X va être implémentée ?</blockquote>
|
||
<p><em>Cliquet</em> est déjà bien garni. Plutôt qu&#8217;implémenter la fonctionnalité X,
|
||
il y a de grandes chances que nous agissions pour s&#8217;assurer que les abstractions
|
||
et les mécanismes d&#8217;extension fournis permettent de l&#8217;implémenter sous forme&nbsp;d&#8217;extension.</p>
|
||
</div>
|
||
</div>
|
||
</content><category term="code"></category></entry><entry><title>Charte et événements non-mixtes au sein de l’Afpy</title><link href="https://blog.notmyidea.org/charte-et-evenements-non-mixtes-au-sein-de-lafpy.html" rel="alternate"></link><published>2015-07-09T00:00:00+02:00</published><updated>2015-07-09T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-07-09:/charte-et-evenements-non-mixtes-au-sein-de-lafpy.html</id><summary type="html">
|
||
<p><em>Mail envoyé sur la liste de diffusion de l&#8217;<span class="caps">AFPY</span> en Juillet&nbsp;2015</em></p>
|
||
<p>Bonjour à toutes et&nbsp;tous,</p>
|
||
<p>Récemment, l&#8217;Afpy à pris la décision de ne pas relayer la tenue d&#8217;un
|
||
événement non-mixte d&#8217;apprentissage de Python organisé par PyLadies&nbsp;[0].</p>
|
||
<p>La raison est le fait que la …</p></summary><content type="html">
|
||
<p><em>Mail envoyé sur la liste de diffusion de l&#8217;<span class="caps">AFPY</span> en Juillet&nbsp;2015</em></p>
|
||
<p>Bonjour à toutes et&nbsp;tous,</p>
|
||
<p>Récemment, l&#8217;Afpy à pris la décision de ne pas relayer la tenue d&#8217;un
|
||
événement non-mixte d&#8217;apprentissage de Python organisé par PyLadies&nbsp;[0].</p>
|
||
<p>La raison est le fait que la tenue d&#8217;un tel événement ne respecte pas la
|
||
charte [1], et particulièrement le fait que c&#8217;est un événement
|
||
discriminant, alors que toutes les discriminations cherchent à être&nbsp;évitées.</p>
|
||
<blockquote>
|
||
<p>L’<span class="caps">AFPY</span> souhaite éviter tout type de discrimination, que ce soit sur
|
||
le sexe, l’orientation sexuelle, le handicap, l’apparence physique,
|
||
l’origine ou la religion, et sous quelque forme que ce soit (parole,
|
||
image, texte et&nbsp;autre).</p>
|
||
</blockquote>
|
||
<p>Je suis un peu attristé que notre charte actuelle ne nous permette pas
|
||
de soutenir de telles propositions: les événements non-mixtes pour les
|
||
minorités sont des pratiques qui existent depuis longtemps, et qui ont
|
||
notamment été instrumentales dans la lutte contre l’apartheid&nbsp;[2].</p>
|
||
<p>Et donc je voudrais voir cette charte évoluer si possible, mais j&#8217;ai du
|
||
mal à voir comment travailler le texte pour qu&#8217;il permette la tenue
|
||
d&#8217;événements non-mixtes au sein même de&nbsp;l&#8217;Afpy.</p>
|
||
<p>Qu&#8217;est-ce que vous en pensez&nbsp;?</p>
|
||
<p>—&nbsp;Alexis</p>
|
||
<p>[0] http://www.meetup.com/fr/PyLadies-Paris/
|
||
[1] http://www.afpy.org/doc/afpy/charte.html
|
||
[2] Une citation à ce&nbsp;propos:</p>
|
||
<p>« La pratique de la non-mixité est tout simplement la conséquence de la
|
||
théorie de l’auto-émancipation. L’auto-émancipation, c’est la lutte par
|
||
les opprimés pour les opprimés. Cette idée simple, il semble que chaque
|
||
génération politique doive la redécouvrir. Dans les années 1960, elle a
|
||
d’abord été redécouverte par le mouvement américain pour les droits
|
||
civils qui, après deux ans de lutte mixte, a décidé de créer des groupes
|
||
noirs, fermés aux Blancs. C’était, cela demeure, la&nbsp;condition</p>
|
||
<ul>
|
||
<li>pour que leur expérience de discrimination et d’humiliation puisse se
|
||
dire, sans crainte de faire de la peine aux bons Blancs&nbsp;;</li>
|
||
<li>pour que la rancœur puisse s’exprimer – et elle doit s’exprimer&nbsp;;</li>
|
||
<li>pour que l’admiration que les opprimés, même révoltés, ne peuvent
|
||
s’empêcher d’avoir pour les dominants – les noirs pour les Blancs, les
|
||
femmes pour les hommes – ne joue pas pour donner plus de poids aux
|
||
représentants du groupe&nbsp;dominant.</li>
|
||
</ul>
|
||
<p>Car dans les groupes mixtes, Noirs-Blancs ou femmes-hommes, et en
|
||
général dans les groupes dominés-dominants, c’est la vision dominante du
|
||
préjudice subi par le groupe dominé qui tend à… dominer. Les opprimés
|
||
doivent non seulement diriger la lutte contre leur oppression, mais
|
||
auparavant définir cette oppression elles et eux-mêmes. C’est pourquoi
|
||
la non-mixité voulue, la non-mixité politique, doit demeurer la pratique
|
||
de base de toute lutte ; et c’est seulement ainsi que les moments mixtes
|
||
de la lutte – car il y en a et il faut qu’il y en ait – ne seront pas
|
||
susceptibles de déraper vers une reconduction douce de la&nbsp;domination.»</p>
|
||
<p>&#8212;&nbsp;http://lmsi.net/La-non-mixite-une-necessite</p></content><category term="journal"></category></entry><entry><title>Service de nuages : Perspectives pour l’été</title><link href="https://blog.notmyidea.org/service-de-nuages-perspectives-pour-lete-fr.html" rel="alternate"></link><published>2015-07-07T00:00:00+02:00</published><updated>2015-07-07T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-07-07:/service-de-nuages-perspectives-pour-lete-fr.html</id><summary type="html"><p class="first last">Le travail en cours et les fonctionnalités à venir pour les prochains&nbsp;mois.</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p>Mozilla a pour coutume d&#8217;organiser régulièrement des semaines de travail où tous les employés
|
||
sont réunis physiquement. Pour cette dernière édition, nous avons pu retrouver
|
||
nos collègues du monde entier à <a class="reference external" href="http://www.openstreetmap.org/node/268148288#map=4/50.12/-122.95">Whistler, en Colombie Britannique au Canada</a>&nbsp;!</p>
|
||
<img alt="«All Hands» talk about Lego, by &#64;davidcrob - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-talks.jpg" />
|
||
<p>Ce fût l&#8217;occasion pour notre équipe de se retrouver, et surtout de partager notre
|
||
vision et nos idées dans le domaine du stockage, afin de collecter des cas d&#8217;utilisation pour
|
||
notre solution <a class="reference external" href="https://kinto.readthedocs.org">Kinto</a>.</p>
|
||
<p>Dans cet article, nous passons en revue les pistes que nous avons pour
|
||
les prochains&nbsp;mois.</p>
|
||
<div class="section" id="ateliers-et-promotion">
|
||
<h2>Ateliers et&nbsp;promotion</h2>
|
||
<p>Nicolas a présenté <a class="reference external" href="https://github.com/mozilla-services/kinto.js">Kinto.js</a> dans un atelier dédié, avec comme support de
|
||
présentation le <a class="reference external" href="http://kintojs.readthedocs.org/en/latest/tutorial/">tutorial d&#8217;introduction</a>.</p>
|
||
<p>L&#8217;application résultante, pourtant toute simple, permet d&#8217;appréhender les
|
||
concepts de synchronisation de Kinto. Le tout sans installation prélable,
|
||
puisque Rémy a mis en place un <a class="reference external" href="https://kinto.dev.mozaws.net/v1/">serveur de dev effacé tous les jours</a>.</p>
|
||
<p>Nous avions mis un point d&#8217;honneur à faire du Vanilla.<span class="caps">JS</span>, déjà pour éviter les
|
||
combats de clochers autour des frameworks, mais aussi pour mettre en évidence qu&#8217;avec
|
||
<span class="caps">HTML5</span> et <span class="caps">ES6</span>, on n&#8217;était plus aussi démunis qu&#8217;il y a quelques&nbsp;années.</p>
|
||
<p>Ce petit atelier nous a permis de nous rendre compte qu&#8217;on avait encore de
|
||
grosses lacunes en terme de documentation, surtout en ce qui concerne
|
||
l&#8217;éco-système et la vision globale des projets (Kinto, Kinto.js, Cliquet, &#8230;).
|
||
Nous allons donc faire de notre mieux pour combler ce&nbsp;manque.</p>
|
||
<img alt="Kinto.js workshop - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-workshop.jpg" />
|
||
</div>
|
||
<div class="section" id="mozilla-payments">
|
||
<h2>Mozilla&nbsp;Payments</h2>
|
||
<p>Comme <a class="reference external" href="http://www.servicedenuages.fr/la-gestion-des-permissions">décrit précédemment</a>, nous avons mis en place un système de permissions pour répondre aux besoins de suivi des paiements et&nbsp;abonnements.</p>
|
||
<p>Pour ce projet, Kinto sera utilisé depuis une application Django, via un client&nbsp;Python.</p>
|
||
<p>Maintenant que les développements ont été livrés, il faut transformer l&#8217;essai, réussir l&#8217;intégration, l&#8217;hébergement et la montée en puissance. La solution doit être livrée à la fin de&nbsp;l&#8217;année.</p>
|
||
<div class="section" id="a-venir">
|
||
<h3>À&nbsp;venir</h3>
|
||
<p>Nous aimerions en profiter pour implémenter une fonctionnalité qui nous tient à coeur : la construction de la liste des enregistrements accessibles en lecture sur une collection&nbsp;partagée.</p>
|
||
<img alt="Whistler Alta Lake - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-lake.jpg" />
|
||
</div>
|
||
</div>
|
||
<div class="section" id="firefox-os-et-stockage">
|
||
<h2>Firefox <span class="caps">OS</span> et&nbsp;stockage</h2>
|
||
<p>Nous avons eu beaucoup d&#8217;échanges avec l&#8217;équipe de Firefox <span class="caps">OS</span>, avec qui nous avions
|
||
déjà eu l&#8217;occasion de collaborer, pour le <a class="reference external" href="https://github.com/mozilla-services/msisdn-gateway">serveur d&#8217;identification BrowserID par <span class="caps">SMS</span></a> et pour <a class="reference external" href="https://github.com/mozilla-services/loop-server">Firefox Hello</a>.</p>
|
||
<div class="section" id="in-app-sync">
|
||
<h3>In-App&nbsp;sync</h3>
|
||
<p>Kinto, la solution simple promue pour la synchronisation de données dans les applications
|
||
Firefox <span class="caps">OS</span> ? La classe ! C&#8217;est ce qu&#8217;on avait en tête depuis longtemps, déjà à
|
||
l&#8217;époque avec <a class="reference external" href="http://daybed.readthedocs.org/">Daybed</a>. Voici donc une belle opportunité à saisir&nbsp;!</p>
|
||
<p>Il va falloir expliciter les limitations et hypothèses simplificatrices de notre
|
||
solution, surtout en termes de gestion de la concurrence. Nous sommes persuadés
|
||
que ça colle avec la plupart des besoins, mais il ne faudrait pas décevoir&nbsp;:)</p>
|
||
<p>Le fait que <a class="reference external" href="https://github.com/daleharvey">Dale</a>, un des auteurs de <a class="reference external" href="http://pouchdb.com/">PouchDB</a> et <a class="reference external" href="https://github.com/michielbdejong">Michiel de Jong</a>, un des auteurs de <a class="reference external" href="http://remotestorage.io/">Remote Storage</a>, nous aient encouragés sur nos premiers pas nous a bien motivé&nbsp;!</p>
|
||
</div>
|
||
<div class="section" id="cut-the-rope">
|
||
<h3>Cut the&nbsp;Rope</h3>
|
||
<p>Kinto devrait être mis à profit pour synchroniser les paramètres et les scores
|
||
du <a class="reference external" href="http://mozilla.cuttherope.net/">jeu</a>. Un premier exercice et une première vitrine sympas&nbsp;!</p>
|
||
</div>
|
||
<div class="section" id="syncto">
|
||
<h3>« SyncTo&nbsp;»</h3>
|
||
<p><a class="reference external" href="https://docs.services.mozilla.com/storage/apis-1.5.html">Firefox Sync</a> est la solution qui permet de synchroniser les données de Firefox (favoris, extensions, historique, complétion des formulaires, mots de passe, &#8230;) entre plusieurs périphériques, de manière&nbsp;chiffrée.</p>
|
||
<p>L&#8217;implémentation du client en JavaScript est relativement complexe et date un peu maintenant.
|
||
Le code existant n&#8217;est pas vraiment portable dans <em>Firefox <span class="caps">OS</span></em> et les tentatives de réécriture
|
||
n&#8217;ont pas&nbsp;abouti.</p>
|
||
<p>Nous souhaitons implémenter un pont entre <em>Kinto</em> et <em>Firefox Sync</em>, de manière
|
||
à pouvoir utiliser le client <em>Kinto.js</em>, plus simple et plus moderne, pour récupérer
|
||
les contenus et les stocker dans IndexedDB. Le delta à implémenter côté serveur est faible car nous nous étions
|
||
inspirés du protocole déjà éprouvé de Sync. Côté client, il s&#8217;agira surtout de
|
||
câbler l&#8217;authentification BrowserId et la&nbsp;Crypto.</p>
|
||
<p>Alexis a sauté sur l&#8217;occasion pour commencer l&#8217;écriture d&#8217;<a class="reference external" href="https://github.com/mozilla-services/syncclient">un client python pour Firefox Sync</a>, qui servira de brique de base pour l&#8217;écriture du&nbsp;service.</p>
|
||
</div>
|
||
<div class="section" id="cloud-storage">
|
||
<h3>Cloud&nbsp;Storage</h3>
|
||
<p>Eden Chuang et Sean Lee ont présenté les avancées sur l&#8217;intégration de services de stockages
|
||
distants (<em>DropBox, Baidu Yun</em>) dans <em>Firefox <span class="caps">OS</span></em>. Actuellement, leur preuve de
|
||
concept repose sur <a class="reference external" href="https://fr.wikipedia.org/wiki/Filesystem_in_Userspace"><span class="caps">FUSE</span></a>.</p>
|
||
<p>Nous avons évidemment en tête d&#8217;introduire la notion de fichiers attachés dans
|
||
<em>Kinto</em>, en implémentant la specification
|
||
<a class="reference external" href="https://tools.ietf.org/html/draft-dejong-remotestorage-05">*Remote Storage*</a>,
|
||
mais pour l&#8217;instant les cas d&#8217;utilisations ne se sont pas encore présentés&nbsp;officiellement.</p>
|
||
</div>
|
||
<div class="section" id="a-venir-1">
|
||
<h3>À&nbsp;venir</h3>
|
||
<p>Nous serons probablement amenés à introduire la gestion de la concurrence dans
|
||
le client <span class="caps">JS</span>, en complément de ce qui a été fait sur le serveur, pour permettre
|
||
les écritures simultanées et synchronisation en tâche de&nbsp;fond.</p>
|
||
<p>Nous sommes par ailleurs perpétuellement preneurs de vos retours — et bien
|
||
entendu de vos contributions — tant sur le code <a class="reference external" href="https://github.com/mozilla-services/kinto/">serveur</a>
|
||
que <a class="reference external" href="https://github.com/mozilla-services/kinto.js/">client</a>&nbsp;!</p>
|
||
<img alt="Firefox OS Cloud Storage Presentation - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-cloud-storage.jpg" />
|
||
</div>
|
||
</div>
|
||
<div class="section" id="contenus-applicatifs-de-firefox">
|
||
<h2>Contenus applicatifs de&nbsp;Firefox</h2>
|
||
<p>Aujourd&#8217;hui Firefox a un cycle de release de six semaines. Un des objectifs
|
||
consiste à désolidariser certains contenus applicatifs de ces cycles
|
||
relativement longs (ex. <em>règles de securité, dictionnaires, traductions, &#8230;</em>) <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a>.</p>
|
||
<p>Il s&#8217;agit de données <span class="caps">JSON</span> et binaire qui doivent être versionnées et synchronisées par
|
||
les navigateurs (<em>lecture seule</em>).</p>
|
||
<p>Il y a plusieurs outils officiels qui existent pour gérer ça (<em>Balrog</em>, <em>Shavar</em>, &#8230;),
|
||
et pour l&#8217;instant, aucun choix n&#8217;a été fait. Mais lors des conversations avec
|
||
l&#8217;équipe en charge du projet, ce fût vraiment motivant de voir que même pour
|
||
ce genre de besoins internes, <em>Kinto</em> est tout aussi pertinent&nbsp;!</p>
|
||
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>La bonne nouvelle c&#8217;est que toutes les fonctionnalités <em>third-party</em> qui ont
|
||
été intégrées récemment vont redevenir des <em>add-ons</em> \o/.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<img alt="Landscape - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-landscape.jpg" />
|
||
</div>
|
||
<div class="section" id="awesome-bar">
|
||
<h2>Awesome&nbsp;bar</h2>
|
||
<p>L&#8217;équipe <em>Firefox Labs</em>, le laboratoire qui élève des pandas roux en éprouvette,
|
||
serait vraiment intéressé par notre solution, notamment pour abreuver en données
|
||
un prototype pour améliorer <em>Awesome bar</em>, qui fusionnerait <span class="caps">URL</span>, historique et&nbsp;recherche.</p>
|
||
<p>Nous ne pouvons pas en dire beaucoup plus pour l&#8217;instant, mais les fonctionnalités
|
||
de collections d&#8217;enregistrements partagées entre utilisateurs de <em>Kinto</em>
|
||
correspondent parfaitement à ce qui est envisagé pour le futur du navigateur&nbsp;:)</p>
|
||
<div class="section" id="a-venir-2">
|
||
<h3>À&nbsp;venir</h3>
|
||
<p>Nous serons donc probablement amenés, avant de la fin de l&#8217;année, à introduire des
|
||
fonctionnalités d&#8217;indexation et de recherche <em>full-text</em> (comprendre <em>ElasticSearch</em>).
|
||
Cela rejoint nos plans précédents, puisque c&#8217;est quelque chose que nous avions dans
|
||
<em>Daybed</em>, et qui figurait sur notre feuille de route&nbsp;!</p>
|
||
<img alt="Firefox Labs Meeting - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-labs.jpg" />
|
||
</div>
|
||
</div>
|
||
<div class="section" id="browser-html">
|
||
<h2>Browser.html</h2>
|
||
<p>L&#8217;équipe <em>Recherche</em> explore les notions de plateforme, et travaille notamment
|
||
sur l&#8217;implémentation d&#8217;un navigateur en <span class="caps">JS</span>/<span class="caps">HTML</span> avec <em>React</em>:
|
||
<a class="reference external" href="https://github.com/mozilla/browser.html">browser.html</a></p>
|
||
<p><em>Kinto</em> correspond parfaitement aux attentes
|
||
de l&#8217;équipe pour synchroniser les données associées à un&nbsp;utilisateur.</p>
|
||
<p>Il pourrait s&#8217;agir de données de navigation (comme Sync), mais aussi de collections
|
||
d&#8217;enregistrements diverses, comme par exemple les préférences du navigateur
|
||
ou un équivalent à <em>Alexa.com Top 500</em> pour fournir la complétion d&#8217;<span class="caps">URL</span> sans
|
||
interroger le moteur de&nbsp;recherche.</p>
|
||
<p>L&#8217;exercice pourrait être poussé jusqu&#8217;à la synchronisation d&#8217;états <em>React</em>
|
||
entre périphériques (par exemple pour les&nbsp;onglets).</p>
|
||
<div class="section" id="a-venir-3">
|
||
<h3>À&nbsp;venir</h3>
|
||
<p>Si <em>browser.html</em> doit stocker des données de navigation, il faudra ajouter
|
||
des fonctionnalités de chiffrement sur le client <span class="caps">JS</span>. Ça tombe bien, c&#8217;est un
|
||
sujet passionant, et <a class="reference external" href="http://www.w3.org/TR/WebCryptoAPI/">il y a plusieurs standards</a>&nbsp;!</p>
|
||
<p>Pour éviter d&#8217;interroger le serveur à intervalle régulier afin de synchroniser les
|
||
changements, l&#8217;introduction des <a class="reference external" href="https://w3c.github.io/push-api/">*push notifications*</a> semble assez naturelle.
|
||
Il s&#8217;agirait alors de la dernière pierre qui manque à l&#8217;édifice pour obtenir
|
||
un «<em>Mobile/Web backend as a service</em>»&nbsp;complet.</p>
|
||
<img alt="Roadmap - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-roadmap.jpg" />
|
||
</div>
|
||
</div>
|
||
<div class="section" id="conclusion">
|
||
<h2>Conclusion</h2>
|
||
<p>Nous sommes dans une situation idéale, puisque ce que nous avions imaginé
|
||
sur <a class="reference external" href="https://github.com/mozilla-services/kinto/wiki/Roadmap">notre feuille de route</a> correspond à ce qui nous est demandé par les
|
||
différentes&nbsp;équipes.</p>
|
||
<p>L&#8217;enjeu consiste maintenant à se coordonner avec tout le monde, ne pas décevoir,
|
||
tenir la charge, continuer à améliorer et à faire la promotion du produit, se concentrer
|
||
sur les prochaines étapes et embarquer quelques contributeurs à nos cotés pour
|
||
construire une solution libre, générique, simple et auto-hébergeable pour le stockage
|
||
de données sur le Web&nbsp;:)</p>
|
||
<img alt="Friday Night Party - CC0" class="align-center" src="https://blog.notmyidea.org/images/whistler/whistler-top-roof.jpg" />
|
||
</div>
|
||
</content><category term="code"></category></entry><entry><title>Rôles</title><link href="https://blog.notmyidea.org/roles.html" rel="alternate"></link><published>2015-06-29T00:00:00+02:00</published><updated>2015-06-29T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-06-29:/roles.html</id><summary type="html"><p>Headline : De l&#8217;importance des rôles informels et de leur partage au sein d&#8217;un&nbsp;groupe.</p>
|
||
<blockquote>
|
||
<p>Un […] dispositif consiste à tenter de faire bouger les rôles
|
||
(pré)acquis ou qui se fixent dans le groupe, les pousser ailleurs que
|
||
là où ils ont pris l’habitude de se réfugier suivant …</p></blockquote></summary><content type="html"><p>Headline : De l&#8217;importance des rôles informels et de leur partage au sein d&#8217;un&nbsp;groupe.</p>
|
||
<blockquote>
|
||
<p>Un […] dispositif consiste à tenter de faire bouger les rôles
|
||
(pré)acquis ou qui se fixent dans le groupe, les pousser ailleurs que
|
||
là où ils ont pris l’habitude de se réfugier suivant leur pente «
|
||
naturelle&nbsp;».</p>
|
||
<p>Pour ce faire, le groupe prendra du temps pour identifier les types de
|
||
positions qu’adoptent ses protagonistes et les affects qui y sont
|
||
liés, imaginer ensuite des questions à résoudre ou des propositions à
|
||
travailler qui soient susceptibles d’enrichir la palette, les couleurs
|
||
de la fonction de chacun dans le groupe et les manières qui sont les
|
||
siennes d’intervenir et de faire évoluer&nbsp;l’histoire.</p>
|
||
<p>&#8212; David Vercauteren, <a href="http://micropolitiques.collectifs.net/Role">Micropolitiques des&nbsp;groupes</a></p>
|
||
</blockquote>
|
||
<p>Réussir la transformation d&#8217;un espace compétitif vers un groupe soudé
|
||
demande de réaliser quels sont les points forts de chacun au sein d&#8217;un&nbsp;groupe.</p>
|
||
<p>Une solution évoquée par <a href="http://www.starhawk.org/about/">StarHawk</a>,
|
||
reprise par <em>David Vercauteren</em> repose sur l&#8217;existence de rôles
|
||
informels au sein des groupes et la nécessité de les faire tourner
|
||
(ainsi que les responsabilités&nbsp;attachées).</p>
|
||
<p>Parmi les rôles principaux, quelques autres&nbsp;citations:</p>
|
||
<div class="note">
|
||
|
||
<div class="admonition-title">
|
||
|
||
Note
|
||
|
||
</div>
|
||
|
||
l&#8217;emphase est de mon fait, et je retravaillé très legèrement certains
|
||
passages afin d&#8217;avoir une lecture plus fluide. Je vous invite à suivre
|
||
les liens pour voir les &#8220;questions que chaque rôle fait exister&#8221;, et
|
||
poursuivre la lecture du livre, qui est entièrement disponible en
|
||
ligne.
|
||
|
||
</div>
|
||
|
||
<h2 id="les-corbeaux"><a href="http://micropolitiques.collectifs.net/Role?artpage=2-5#outil_sommaire_0">Les&nbsp;corbeaux</a></h2>
|
||
<blockquote>
|
||
<p>Les Corbeaux sont visionnaires […] Ils voient à long terme, et
|
||
gardent en ligne de mire les objectifs du groupe. Ils suggèrent de
|
||
nouvelles directions, dressent des plans, développent des stratégies
|
||
et anticipent les problèmes et les&nbsp;besoins.</p>
|
||
<p>Les Corbeaux ont souvent beaucoup d’influence sur le groupe. Si une ou
|
||
deux personnes pensent à des plans au long-terme, les autres
|
||
acquiesceront, simplement parce qu’ils n’ont pas amené d’autres
|
||
propositions. <strong>Le groupe aurait intérêt à considérer ensemble les
|
||
questions du&nbsp;Corbeau</strong></p>
|
||
</blockquote>
|
||
<h2 id="les-graces"><a href="http://micropolitiques.collectifs.net/Role?artpage=2-5#outil_sommaire_1">Les&nbsp;graces</a></h2>
|
||
<blockquote>
|
||
<p>Les Grâces sont toujours attentives à l’énergie du groupe, prêtes à la
|
||
renforcer au moment où elle faiblit, à la diriger et à la canaliser
|
||
quand elle est&nbsp;forte.</p>
|
||
<p>Elles apportent au groupe […] enthousiasme, énergie, capacité à
|
||
s’agrandir. <strong>Elles font en sorte que les gens se sentent bien</strong>,
|
||
génèrent de l’enthousiasme pour le groupe, accueillent les nouveaux
|
||
venus, amènent de nouvelles personnes. Elles offrent au groupe
|
||
l’inspiration et génèrent de nouvelles&nbsp;idées.</p>
|
||
</blockquote>
|
||
<h2 id="les-dragons"><a href="http://micropolitiques.collectifs.net/Role?artpage=2-5#outil_sommaire_2">Les&nbsp;dragons</a></h2>
|
||
<blockquote>
|
||
<p>Le dragon permet au groupe de rester connecté à […] l’aspect
|
||
pratique et réaliste des choses. […] Le dragon veille aux ressources
|
||
du groupe, à ses frontières et donne voix à ses&nbsp;limites.</p>
|
||
<p>Questions que fait exister le&nbsp;dragon:</p>
|
||
<ul>
|
||
<li>Notre manière de travailler est-elle viable&nbsp;?</li>
|
||
<li>Nos ressources sont-elles renouvelées&nbsp;?</li>
|
||
<li>Les gens s’épuisent-ils ? Pourquoi&nbsp;?</li>
|
||
<li>Pouvons-nous vraiment nous lancer dans ce projet et le mener à
|
||
bien convenablement&nbsp;?</li>
|
||
<li>De quelles frontières avec l’extérieur avons-nous besoin et
|
||
voulons-nous&nbsp;?</li>
|
||
<li>Comment établissons-nous ces frontières ? Comment nous
|
||
protégeons-nous des intrusions ? Invasions ? Distractions ? De ce
|
||
qui épuise nos énergies&nbsp;?</li>
|
||
</ul>
|
||
<p><strong>Les Dragons établissent des frontières qui donnent au groupe un
|
||
sentiment de sécurité et des limites qui le rendent viable dans le
|
||
temps</strong>. Ils peuvent être perçus comme des rabat-joie, mais ils
|
||
peuvent gagner l’estime de ceux qui, dans le groupe, se sentent
|
||
dépassés et ne peuvent partager l’énergie des Corbeaux et des&nbsp;Grâces.</p>
|
||
<p>Nourrir les Dragons peut permettre au groupe de se maintenir dans le
|
||
temps. Mais une fois encore, si ce rôle ne tourne pas, même les
|
||
Dragons risquent de&nbsp;s’épuiser.</p>
|
||
</blockquote>
|
||
<h2 id="les-araignees"><a href="http://micropolitiques.collectifs.net/Role?artpage=2-5#outil_sommaire_3">Les&nbsp;araignées</a></h2>
|
||
<blockquote>
|
||
<p>Le centre d’un groupe peut consister en un « cœur spirituel », <strong>un
|
||
but ou une vision commune</strong>, ou peut se manifester à travers une
|
||
personne. Dans les modes de pensée hiérarchique, le professeur ou le
|
||
gourou occupe le centre du réseau.&nbsp;[…]</p>
|
||
<p>Dans les groupes non-hiérarchiques, certaines personnes peuvent être
|
||
perçues comme centrales : en disposant des informations dont les
|
||
autres ont besoin, en étant le point de contact pour les&nbsp;autres.</p>
|
||
<p>Une Araignée est toutefois plus efficace en ne monopolisant pas la
|
||
communication et les informations mais en posant les questions
|
||
susceptibles de créer et de renforcer un véritable réseau
|
||
d’interactions&nbsp;complexes.</p>
|
||
</blockquote>
|
||
<h2 id="les-serpents"><a href="http://micropolitiques.collectifs.net/Role?artpage=2-5#outil_sommaire_4">Les&nbsp;serpents</a></h2>
|
||
<blockquote>
|
||
<p>Les serpents cultivent une attention particulière à la manière dont
|
||
les gens se sentent.&nbsp;[…]</p>
|
||
<p>Les serpents sont au courant de ce qui se murmure dans les couloirs,
|
||
des conflits naissants, et les mettent sur la place publique, là où
|
||
ils pourraient aider à une médiation, à une résolution du problème.&nbsp;[…]</p>
|
||
<p>Les serpents transgressent les lois du Censeur, <strong>parlent des
|
||
non-dits, mettent en évidence ce que d’autres ne voient pas ou
|
||
préfèrent garder caché</strong>.&nbsp;[…]</p>
|
||
<p>Les serpents peuvent diminuer l’antipathie dont ils font l’objet s’ils
|
||
prennent la peine de poser des questions au groupe et non d’apporter
|
||
des&nbsp;analyses.</p>
|
||
</blockquote>
|
||
<p>Ainsi, il est possible de se rendre compte de la complexité et de
|
||
l&#8217;importance d&#8217;une position ou d&#8217;une autre, et de les faire évoluer
|
||
ensemble, en prenant en compte leur impact positif sur le&nbsp;groupe.</p>
|
||
<p>Il est par exemple possible, après avoir expérimenté des rôles, de
|
||
questionner leur pertinence et d&#8217;établir des pistes d&#8217;amélioration en
|
||
enlevant une part importante d&#8217;affect personnel qui parfois empêche des
|
||
discussions&nbsp;constructives.</p>
|
||
<p>Je n&#8217;ai pour l&#8217;instant pas pu expérimenter l&#8217;évolution des rôles au sein
|
||
d&#8217;un groupe donné, mais je peux d&#8217;ores et déjà me rendre compte que
|
||
selon les groupes et selon les moments je n&#8217;ai pas le même rôle (tour à
|
||
tour dragon, araignée et grace, parfois corbeau, rarement&nbsp;serpent)</p>
|
||
<p>Aussi, il semble que le groupe doive souhaiter l&#8217;établissement d&#8217;un
|
||
environnement <em>horizontal</em>, avec une considération partagée de la
|
||
direction que le groupe souhaite prendre pour qu&#8217;un tel dispositif ait
|
||
du&nbsp;sens.</p></content><category term="journal"></category></entry><entry><title>Service de nuages : Achievement unlocked</title><link href="https://blog.notmyidea.org/service-de-nuages-achievement-unlocked-fr.html" rel="alternate"></link><published>2015-06-01T00:00:00+02:00</published><updated>2015-06-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-06-01:/service-de-nuages-achievement-unlocked-fr.html</id><summary type="html"><p class="first last">Après près de 3 mois intensifs, nous venons de <em>tagguer</em> Cliquet 2.0
|
||
et Kinto 1.0&nbsp;!</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p>Aujourd&#8217;hui, c&#8217;est jour de fête : nous venons de publier Cliquet <strong>2.0</strong>
|
||
<a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a> et Kinto <strong>1.0</strong> <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a>.</p>
|
||
<blockquote class="epigraph">
|
||
<p>L&#8217;aboutissement de 3 années de R&amp;D&nbsp;!</p>
|
||
<p class="attribution">&mdash;Rémy</p>
|
||
</blockquote>
|
||
<p><a class="reference external" href="https://kinto.readthedocs.org/en/latest/">Kinto</a> est un service pour
|
||
stocker, synchroniser et partager des données arbitraires, attachées à un
|
||
compte Firefox (mais le système d&#8217;authentification est <em>pluggable</em>).</p>
|
||
<p><a class="reference external" href="https://cliquet.readthedocs.org/en/latest/">Cliquet</a> est une boite à outils pour faciliter l&#8217;implémentation de
|
||
micro-services <span class="caps">HTTP</span> tels que les APIs <em><span class="caps">REST</span></em> ayant des besoins de&nbsp;synchronisation.</p>
|
||
<p>Vous pouvez lire plus à propos des raisons qui nous ont poussé à proposer cette nouvelle solution
|
||
et de notre ambition sur <a class="reference external" href="http://www.servicedenuages.fr/eco-systeme-et-stockage-generique.html">http://www.servicedenuages.fr/eco-systeme-et-stockage-generique.html</a></p>
|
||
<p>Nous sommes fiers du travail que nous avons pu réaliser durant ces derniers
|
||
mois sur ces deux projets. Bien que la plupart du travail que nous ayons
|
||
réalisé pour le serveur de liste de lecture (Reading List) ait pu être utilisé,
|
||
beaucoup de parties ont été repensées et nous avons introduit des
|
||
fonctionnalités que l&#8217;on attendait depuis longtemps, comme la gestion des&nbsp;permissions.</p>
|
||
<p>Bien sur, exactement comme après un ré-aménagement de salon, on ne peut
|
||
s&#8217;empêcher de voir toutes les choses qui doivent toujours être améliorées,
|
||
notamment sur la documentation et les&nbsp;performances.</p>
|
||
<p>On peut déjà entrevoir à quoi l&#8217;écosystème va ressembler, et c&#8217;est prometteur.
|
||
Il y a déjà un client JavaScript <a class="footnote-reference" href="#footnote-3" id="footnote-reference-3">[3]</a> dont l&#8217;objectif est de synchroniser les
|
||
données locales du navigateur avec une instance de&nbsp;Kinto.</p>
|
||
<p>N&#8217;hésitez vraiment pas à nous solliciter pour discuter avec vous si vous avez
|
||
des problématiques proches : nous accueillons avec plaisir toutes sortes de
|
||
retours, que ce soit à propos du code, de la documentation, de la sécurité de
|
||
la solution ou de la manière de communiquer avec le monde extérieur. Si vous
|
||
souhaitez nous contacter, vous pouvez laisser un commentaire ici ou nous
|
||
contacter sur le canal <a class="reference external" href="irc://irc.mozilla.org/#storage">#storage</a> sur le réseau <span class="caps">IRC</span> de&nbsp;Mozilla.</p>
|
||
<p>Et ce n&#8217;est que le début ! Le futur se dessine dans notre feuille de route
|
||
<a class="footnote-reference" href="#footnote-4" id="footnote-reference-4">[4]</a>.</p>
|
||
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td><strong>Cliquet</strong> est une boite à outils pour faciliter l&#8217;implémentation de
|
||
microservices <span class="caps">HTTP</span> tels que les APIs <em><span class="caps">REST</span></em> ayant des besoins de
|
||
synchronisation.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td><strong>Kinto</strong> est un service pour stocker, synchroniser et partager des données
|
||
arbitraires, attachées à un compte Firefox (mais le système d&#8217;authentification
|
||
est <em>pluggable</em>).</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="footnote-3" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-3">[3]</a></td><td>Cliquetis, la bibliothèque JavaScript pour consommer l&#8217;<span class="caps">API</span> <span class="caps">HTTP</span> de Kinto —
|
||
<a class="reference external" href="https://github.com/mozilla-services/cliquetis">https://github.com/mozilla-services/cliquetis</a></td></tr>
|
||
</tbody>
|
||
</table>
|
||
<table class="docutils footnote" frame="void" id="footnote-4" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-4">[4]</a></td><td>La feuille de route de Kinto: <a class="reference external" href="https://github.com/mozilla-services/kinto/wiki/roadmap">https://github.com/mozilla-services/kinto/wiki/roadmap</a></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</content><category term="code"></category></entry><entry><title>Service de nuages : Stocker et interroger les permissions avec Kinto</title><link href="https://blog.notmyidea.org/service-de-nuages-stocker-et-interroger-les-permissions-avec-kinto-fr.html" rel="alternate"></link><published>2015-05-26T00:00:00+02:00</published><updated>2015-05-26T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-26:/service-de-nuages-stocker-et-interroger-les-permissions-avec-kinto-fr.html</id><summary type="html"><p class="first last">Comment faire pour stocker et interroger la base de données au sujet des permissions avec Kinto&nbsp;?</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p><strong>tl;dr: On a maintenant un super système de permission mais comment faire pour stocker et interroger ces permissions de manière efficace&nbsp;?</strong></p>
|
||
<div class="section" id="la-problematique">
|
||
<h2>La&nbsp;problématique</h2>
|
||
<p>Maintenant que nous avons défini un modèle de gestion des permissions
|
||
sur les objets qui nous satisfait, le problème est de stocker ces
|
||
permissions de manière efficace afin de pouvoir autoriser ou interdire
|
||
l&#8217;accès à un objet pour la personne qui fait la&nbsp;requête.</p>
|
||
<p>Chaque requête sur notre <span class="caps">API</span> va générer une ou plusieurs demandes
|
||
d&#8217;accès, il faut donc que la réponse soit très rapide sous peine
|
||
d&#8217;impacter la vélocité du&nbsp;service.</p>
|
||
</div>
|
||
<div class="section" id="obtenir-la-liste-des-principals-d-un-utilisateur">
|
||
<h2>Obtenir la liste des &#8220;principals&#8221; d&#8217;un&nbsp;utilisateur</h2>
|
||
<p>Les <em>principals</em> de l&#8217;utilisateur correspondent à son <tt class="docutils literal">user_id</tt>
|
||
ainsi qu&#8217;à la liste des identifiants des groupes dans lesquels il a
|
||
été&nbsp;ajouté.</p>
|
||
<p>Pour éviter de recalculer les <em>principals</em> de l&#8217;utilisateur à chaque
|
||
requête, le mieux reste de maintenir une liste des <em>principals</em> par&nbsp;utilisateur.</p>
|
||
<p>Ainsi lorsqu&#8217;on ajoute un utilisateur à un groupe, il faut bien penser
|
||
à ajouter le groupe à la liste des <em>principals</em> de&nbsp;l&#8217;utilisateur.</p>
|
||
<p>Ça se complexifie lorsqu&#8217;on ajoute un groupe à un&nbsp;groupe.</p>
|
||
<p>Dans un premier temps interdire l&#8217;ajout d&#8217;un groupe à un groupe est
|
||
une limitation qu&#8217;on est prêts à accepter pour simplifier le&nbsp;modèle.</p>
|
||
<p>L&#8217;avantage de maintenir la liste des <em>principals</em> d&#8217;un utilisateur
|
||
lors de la modification de cette liste c&#8217;est qu&#8217;elle est déjà
|
||
construite lors des lectures, qui sont dans notre cas plus fréquentes
|
||
que les&nbsp;écritures.</p>
|
||
<p>Cela nécessite de donner un identifiant unique aux groupes pour tous
|
||
les <em>buckets</em>.</p>
|
||
<p>Nous proposons de de les nommer avec leur <span class="caps">URI</span>:
|
||
<tt class="docutils literal">/buckets/blog/groups/moderators</tt></p>
|
||
</div>
|
||
<div class="section" id="obtenir-la-liste-des-principals-d-un-ace">
|
||
<h2>Obtenir la liste des &#8220;principals&#8221; d&#8217;un <span class="caps">ACE</span></h2>
|
||
<blockquote>
|
||
Rappel, un &#8220;<span class="caps">ACE</span>&#8221; est un <em>Access Control Entry</em>, un des éléments
|
||
d&#8217;une <span class="caps">ACL</span> (e.g. <em>modifier un enregistrement</em>).</blockquote>
|
||
<p>Avec le <a class="reference external" href="https://blog.notmyidea.org/service-de-nuages-la-gestion-des-permissions-fr.html">système de permissions choisi</a>, les permissions d&#8217;un
|
||
objet héritent de celle de l&#8217;objet&nbsp;parent.</p>
|
||
<p>Par exemple, avoir le droit d&#8217;écriture sur un <em>bucket</em> permet la
|
||
création des permissions et la modification de tous ses&nbsp;records.</p>
|
||
<p>Ce qui veut dire que pour obtenir la liste complète des <em>principals</em>
|
||
ayant une permission sur un objet, il faut regarder à plusieurs&nbsp;endroits.</p>
|
||
<p>Rémy a <a class="reference external" href="https://gist.github.com/Natim/77c8f61c1d42e476cef8#file-permission-py-L9-L52">décrit dans un gist la liste d&#8217;héritage de chaque permission</a>.</p>
|
||
<p>Prenons l&#8217;exemple de l&#8217;ajout d&#8217;un record dans une&nbsp;collection.</p>
|
||
<p>Le droit <tt class="docutils literal">records:create</tt> est obtenu si l&#8217;on a l&#8217;un des droits&nbsp;suivants:</p>
|
||
<ul class="simple">
|
||
<li><tt class="docutils literal">bucket:write</tt></li>
|
||
<li><tt class="docutils literal">collection:write</tt></li>
|
||
<li><tt class="docutils literal">records:create</tt></li>
|
||
</ul>
|
||
<p>Notre première idée était de stocker les permissions sur chaque objet
|
||
et de maintenir la liste exhaustive des permissions lors d&#8217;une
|
||
modification d&#8217;<span class="caps">ACL</span>. Cependant cela nécessitait de construire cette
|
||
liste lors de l&#8217;ajout d&#8217;un objet et de mettre à jour tout l&#8217;arbre lors
|
||
de sa suppression. (<em>Je vous laisse imaginer le nombre d&#8217;opérations
|
||
nécessaires pour ajouter un administrateur sur un *bucket</em> contenant
|
||
1000 collections avec 100000 records&nbsp;chacune.*)</p>
|
||
<p>La solution que nous avons désormais adoptée consiste à stocker les
|
||
<em>principals</em> de chaque <em><span class="caps">ACE</span></em> (<em>qui</em> a le droit de faire telle action
|
||
sur l&#8217;objet), et de faire l&#8217;union des <em><span class="caps">ACE</span></em> hérités, afin de les
|
||
croiser avec les <em>principals</em> de l&#8217;utilisateur&nbsp;:</p>
|
||
<blockquote>
|
||
(<span class="caps">ACE</span>(object, permission) ∪ inherited_ACE) ∩ <span class="caps">PRINCIPALS</span>(user)</blockquote>
|
||
<p>Par exemple l&#8217;<span class="caps">ACE</span>: <tt class="docutils literal">/buckets/blog/collections/article:records:create</tt> hérite de
|
||
l&#8217;<span class="caps">ACE</span> <tt class="docutils literal">/buckets/blog/collections/article:write</tt> et de <tt class="docutils literal">/buckets/blog:write</tt> :</p>
|
||
<blockquote>
|
||
(<span class="caps">ACE</span>(/buckets/blog/collections/article:records:create) ∪ <span class="caps">ACE</span>(/buckets/blog/collections/article:write) ∪ <span class="caps">ACE</span>(/buckets/blog:write)) ∩ <span class="caps">PRINCIPALS</span>(&#8216;fxa:alexis&#8217;)</blockquote>
|
||
</div>
|
||
<div class="section" id="recuperer-les-donnees-de-l-utilisateur">
|
||
<h2>Récupérer les données de&nbsp;l&#8217;utilisateur</h2>
|
||
<p>La situation se corse lorsqu&#8217;on souhaite limiter la liste des
|
||
<em>records</em> d&#8217;une collection à ceux accessibles pour l&#8217;utilisateur, car
|
||
on doit faire cette intersection pour tous les <em>records</em>.</p>
|
||
<p>Une première solution est de regarder si l&#8217;utilisateur est mentionné
|
||
dans les <em><span class="caps">ACL</span>*s du *bucket</em> ou de la <em>collection</em>:</p>
|
||
<p>Ensuite, si ce n&#8217;est pas le cas, alors on filtre les <em>records</em> pour
|
||
lesquels les <em>principals</em> correspondent à ceux de&nbsp;l&#8217;utilisateur.</p>
|
||
<div class="highlight"><pre><span></span><span class="n">principals</span> <span class="o">=</span> <span class="n">get_user_principals</span><span class="p">(</span><span class="n">user_id</span><span class="p">)</span>
|
||
<span class="n">can_read_all</span> <span class="o">=</span> <span class="n">has_read_perms</span><span class="p">(</span><span class="n">bucket_id</span><span class="p">,</span> <span class="n">collection_id</span><span class="p">,</span>
|
||
<span class="n">principals</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="n">can_read_all</span><span class="p">:</span>
|
||
<span class="n">records</span> <span class="o">=</span> <span class="n">get_all_records</span><span class="p">(</span><span class="n">bucket_id</span><span class="p">,</span> <span class="n">collection_id</span><span class="p">,</span>
|
||
<span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="o">...</span><span class="p">])</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">records</span> <span class="o">=</span> <span class="n">filter_read_records</span><span class="p">(</span><span class="n">bucket_id</span><span class="p">,</span> <span class="n">collection_id</span><span class="p">,</span>
|
||
<span class="n">principals</span><span class="o">=</span><span class="n">principals</span><span class="p">,</span>
|
||
<span class="n">filters</span><span class="o">=</span><span class="p">[</span><span class="o">...</span><span class="p">])</span>
|
||
</pre></div>
|
||
<p>Il faudra faire quelque chose de similaire pour la suppression
|
||
multiple, lorsqu&#8217;un utilisateur souhaitera supprimer des
|
||
enregistrements sur lesquels il a les droits de lecture mais pas&nbsp;d&#8217;écriture.</p>
|
||
</div>
|
||
<div class="section" id="le-modele-de-donnees">
|
||
<h2>Le modèle de&nbsp;données</h2>
|
||
<p>Pour avoir une idée des requêtes dans un backend <span class="caps">SQL</span>, voyons un peu ce
|
||
que donnerait le modèle de&nbsp;données.</p>
|
||
<div class="section" id="le-format-des-id">
|
||
<h3>Le format des <span class="caps">ID</span></h3>
|
||
<p>Utiliser des <span class="caps">URI</span> comme identifiant des objets présente de nombreux
|
||
avantages (lisibilité, unicité, cohérence avec les&nbsp;URLs)</p>
|
||
<ul class="simple">
|
||
<li>bucket: <tt class="docutils literal">/buckets/blog</tt></li>
|
||
<li>groupe: <tt class="docutils literal">/buckets/blog/group/moderators</tt></li>
|
||
<li>collection: <tt class="docutils literal">/buckets/blog/collections/articles</tt></li>
|
||
<li>record: <tt class="docutils literal"><span class="pre">/buckets/blog/collections/articles/records/02f3f76f-7059-4ae4-888f-2ac9824e9200</span></tt></li>
|
||
</ul>
|
||
</div>
|
||
<div class="section" id="les-tables">
|
||
<h3>Les&nbsp;tables</h3>
|
||
<p>Pour le stockage des principals et des&nbsp;permissions:</p>
|
||
<div class="highlight"><pre><span></span><span class="k">CREATE</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="k">user</span><span class="p">(</span><span class="n">id</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">,</span><span class="w"> </span><span class="n">principals</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">[]);</span>
|
||
<span class="k">CREATE</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="n">perms</span><span class="p">(</span><span class="n">ace</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">,</span><span class="w"> </span><span class="n">principals</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">[]);</span>
|
||
</pre></div>
|
||
<p>La table <em>perms</em> va associer des <em>principals</em> à chaque <em><span class="caps">ACE</span></em>&nbsp;(e.g.&#8220;/buckets/blog:write&#8220;).</p>
|
||
<p>Pour le stockage des&nbsp;données:</p>
|
||
<div class="highlight"><pre><span></span><span class="k">CREATE</span><span class="w"> </span><span class="k">TABLE</span><span class="w"> </span><span class="k">object</span><span class="p">(</span><span class="n">id</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">,</span><span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">,</span><span class="w"> </span><span class="n">parent_id</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">,</span><span class="w"> </span><span class="k">data</span><span class="w"> </span><span class="n">JSONB</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">write_principals</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">[],</span><span class="w"> </span><span class="n">read_principals</span><span class="w"> </span><span class="nb">TEXT</span><span class="p">[]);</span>
|
||
</pre></div>
|
||
<p>La colonne <em>parent_id</em> permet de savoir à qui appartient l&#8217;objet
|
||
(e.g. groupe d&#8217;un <em>bucket</em>, collection d&#8217;un <em>bucket</em>, <em>record</em> d&#8217;une
|
||
collection,&nbsp;&#8230;).</p>
|
||
</div>
|
||
<div class="section" id="exemple-d-utilisateur">
|
||
<h3>Exemple&nbsp;d&#8217;utilisateur</h3>
|
||
<div class="highlight"><pre><span></span><span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="k">user</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">principals</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">VALUES</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;fxa:alexis&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;{}&#39;</span><span class="p">);</span>
|
||
|
||
<span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="k">user</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">principals</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">VALUES</span><span class="w"> </span><span class="p">(</span><span class="s1">&#39;fxa:natim&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;/buckets/blog/groups/moderators&quot;}&#39;</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="section" id="exemple-d-objets">
|
||
<h3>Exemple&nbsp;d&#8217;objets</h3>
|
||
<div class="section" id="bucket">
|
||
<h4>Bucket</h4>
|
||
<div class="highlight"><pre><span></span><span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="k">type</span><span class="p">,</span><span class="w"> </span><span class="n">parent_id</span><span class="p">,</span><span class="w"> </span><span class="k">data</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">read_principals</span><span class="p">,</span><span class="w"> </span><span class="n">write_principals</span><span class="p">)</span>
|
||
<span class="k">VALUES</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;bucket&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="k">NULL</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;name&quot;: &quot;blog&quot;}&#39;</span><span class="p">::</span><span class="n">JSONB</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{}&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;{&quot;fxa:alexis&quot;}&#39;</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="section" id="group">
|
||
<h4>Group</h4>
|
||
<div class="highlight"><pre><span></span><span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="k">type</span><span class="p">,</span><span class="w"> </span><span class="n">parent_id</span><span class="p">,</span><span class="w"> </span><span class="k">data</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">read_principals</span><span class="p">,</span><span class="w"> </span><span class="n">write_principals</span><span class="p">)</span>
|
||
<span class="k">VALUES</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog/groups/moderators&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;group&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;name&quot;: &quot;moderators&quot;, &quot;members&quot;: [&#39;</span><span class="n">fxa</span><span class="p">:</span><span class="n">natim</span><span class="s1">&#39;]}&#39;</span><span class="p">::</span><span class="n">JSONB</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{}&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;{}&#39;</span><span class="p">);</span>
|
||
</pre></div>
|
||
<p>Ce groupe peut être gére par <tt class="docutils literal">fxa:alexis</tt> puisqu&#8217;il a la permission
|
||
<tt class="docutils literal">write</tt> dans le <em>bucket</em>&nbsp;parent.</p>
|
||
</div>
|
||
<div class="section" id="collection">
|
||
<h4>Collection</h4>
|
||
<div class="highlight"><pre><span></span><span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="k">type</span><span class="p">,</span><span class="w"> </span><span class="n">parent_id</span><span class="p">,</span><span class="w"> </span><span class="k">data</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">read_principals</span><span class="p">,</span><span class="w"> </span><span class="n">write_principals</span><span class="p">)</span>
|
||
<span class="k">VALUES</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog/collections/articles&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;collection&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;name&quot;: &quot;article&quot;}&#39;</span><span class="p">::</span><span class="n">JSONB</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;system.Everyone&quot;}&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;/buckets/blog/groups/moderators&quot;}&#39;</span><span class="p">);</span>
|
||
</pre></div>
|
||
<p>Cette collection d&#8217;articles peut être lue par tout le monde,
|
||
et gérée par les membres du groupe <tt class="docutils literal">moderators</tt>, ainsi que
|
||
<tt class="docutils literal">fxa:alexis</tt>, via le <em>bucket</em>.</p>
|
||
</div>
|
||
<div class="section" id="records">
|
||
<h4>Records</h4>
|
||
<div class="highlight"><pre><span></span><span class="k">INSERT</span><span class="w"> </span><span class="k">INTO</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="k">type</span><span class="p">,</span><span class="w"> </span><span class="n">parent_id</span><span class="p">,</span><span class="w"> </span><span class="k">data</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">read_principals</span><span class="p">,</span><span class="w"> </span><span class="n">write_principals</span><span class="p">)</span>
|
||
<span class="k">VALUES</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog/collections/articles/records/02f3f76f-7059-4ae4-888f-2ac9824e9200&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;record&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog/collections/articles&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{&quot;name&quot;: &quot;02f3f76f-7059-4ae4-888f-2ac9824e9200&quot;,</span>
|
||
<span class="s1"> &quot;title&quot;: &quot;Stocker les permissions&quot;, ...}&#39;</span><span class="p">::</span><span class="n">JSONB</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;{}&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;{}&#39;</span><span class="p">);</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="interroger-les-permissions">
|
||
<h3>Interroger les&nbsp;permissions</h3>
|
||
<div class="section" id="obtenir-la-liste-des-principals-d-un-ace-1">
|
||
<h4>Obtenir la liste des &#8220;principals&#8221; d&#8217;un <span class="caps">ACE</span></h4>
|
||
<p>Comme vu plus haut, pour vérifier une permission, on fait l&#8217;union des
|
||
<em>principals</em> requis par les objets hérités, et on teste leur
|
||
intersection avec ceux de&nbsp;l&#8217;utilisateur:</p>
|
||
<div class="highlight"><pre><span></span><span class="k">WITH</span><span class="w"> </span><span class="n">required_principals</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="k">unnest</span><span class="p">(</span><span class="n">principals</span><span class="p">)</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="n">p</span>
|
||
<span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">perms</span>
|
||
<span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">ace</span><span class="w"> </span><span class="k">IN</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog:write&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog:read&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog/collections/article:write&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="s1">&#39;/buckets/blog/collections/article:read&#39;</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="p">),</span>
|
||
<span class="w"> </span><span class="n">user_principals</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="p">(</span>
|
||
<span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="k">unnest</span><span class="p">(</span><span class="n">principals</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="k">user</span>
|
||
<span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;fxa:natim&#39;</span>
|
||
<span class="w"> </span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">SELECT</span><span class="w"> </span><span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">user_principals</span><span class="w"> </span><span class="n">a</span>
|
||
<span class="w"> </span><span class="k">INNER</span><span class="w"> </span><span class="k">JOIN</span><span class="w"> </span><span class="n">required_principals</span><span class="w"> </span><span class="n">b</span>
|
||
<span class="w"> </span><span class="k">ON</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">b</span><span class="p">.</span><span class="n">p</span><span class="p">;</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="section" id="filtrer-les-objets-en-fonction-des-permissions">
|
||
<h4>Filtrer les objets en fonction des&nbsp;permissions</h4>
|
||
<p>Pour filtrer les objets, on fait une simple intersection de liste
|
||
(<em>merci PostgreSQL</em>):</p>
|
||
<div class="highlight"><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="k">data</span>
|
||
<span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="n">o</span><span class="p">,</span><span class="w"> </span><span class="k">user</span><span class="w"> </span><span class="n">u</span>
|
||
<span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">o</span><span class="p">.</span><span class="k">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;record&#39;</span>
|
||
<span class="w"> </span><span class="k">AND</span><span class="w"> </span><span class="n">o</span><span class="p">.</span><span class="n">parent_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;/buckets/blog/collections/article&#39;</span>
|
||
<span class="w"> </span><span class="k">AND</span><span class="w"> </span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="n">read_principals</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">u</span><span class="p">.</span><span class="n">principals</span><span class="w"> </span><span class="k">OR</span>
|
||
<span class="w"> </span><span class="n">o</span><span class="p">.</span><span class="n">write_principals</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">u</span><span class="p">.</span><span class="n">principals</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="k">AND</span><span class="w"> </span><span class="n">u</span><span class="p">.</span><span class="n">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;fxa:natim&#39;</span><span class="p">;</span>
|
||
</pre></div>
|
||
<p>Les listes s&#8217;indexent bien, notamment grâce aux <a class="reference external" href="http://www.postgresql.org/docs/current/static/indexes-types.html">index <span class="caps">GIN</span></a>.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="avec-redis">
|
||
<h3>Avec&nbsp;Redis</h3>
|
||
<p><em>Redis</em> présente plusieurs avantages pour ce genre de
|
||
problématiques. Notamment, il gère les <em>set</em> nativement (listes de
|
||
valeurs uniques), ainsi que les opérations d&#8217;intersection et&nbsp;d&#8217;union.</p>
|
||
<p>Avec <em>Redis</em> on peut écrire l&#8217;obtention des <em>principals</em> pour un <em><span class="caps">ACE</span></em>
|
||
comme cela&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span>SUNIONSTORE temp_perm:/buckets/blog/collections/articles:write permission:/buckets/blog:write permission:/buckets/blog/collections/articles:write
|
||
SINTER temp_perm:/buckets/blog/collections/articles:write principals:fxa:alexis
|
||
</pre></div>
|
||
<ul class="simple">
|
||
<li><tt class="docutils literal"><span class="caps">SUNIONSTORE</span></tt> permet de créer un set contenant les éléments de
|
||
l&#8217;union de tous les set suivants. Dans notre cas on le nomme
|
||
<tt class="docutils literal"><span class="pre">temp_perm:/buckets/blog/collections/articles:write</span></tt> et il contient
|
||
l&#8217;union des sets d&#8217;ACLs suivants:
|
||
- <tt class="docutils literal"><span class="pre">permission:/buckets/blog:write</span></tt>
|
||
- <tt class="docutils literal"><span class="pre">permission:/buckets/blog/collections/articles:write</span></tt></li>
|
||
<li><tt class="docutils literal"><span class="caps">SINTER</span></tt> retourne l&#8217;intersection de tous les sets passés en paramètres dans notre cas :
|
||
- <tt class="docutils literal"><span class="pre">temp_perm:/buckets/blog/collections/articles:write</span></tt>
|
||
- <tt class="docutils literal">principals:fxa:alexis</tt></li>
|
||
</ul>
|
||
<p>Plus d&#8217;informations sur :
|
||
- <a class="reference external" href="http://redis.io/commands/sinter">http://redis.io/commands/sinter</a>
|
||
- <a class="reference external" href="http://redis.io/commands/sunionstore">http://redis.io/commands/sunionstore</a></p>
|
||
<p>Si le set résultant de la commande <tt class="docutils literal"><span class="caps">SINTER</span></tt> n&#8217;est pas vide, alors
|
||
l&#8217;utilisateur possède la&nbsp;permission.</p>
|
||
<p>On peut ensuite supprimer la clé temporaire <tt class="docutils literal">temp_perm</tt>.</p>
|
||
<p>En utilisant <tt class="docutils literal"><span class="caps">MULTI</span></tt> on peut <a class="reference external" href="https://gist.github.com/Natim/77c8f61c1d42e476cef8#file-permission-py-L117-L124">même faire tout cela au sein d&#8217;une
|
||
transaction</a>
|
||
et garantir ainsi l&#8217;intégrité de la&nbsp;requête.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="conclusion">
|
||
<h2>Conclusion</h2>
|
||
<p>La solution a l&#8217;air simple mais nous a demandé beaucoup de réflexion
|
||
en passant par plusieurs&nbsp;propositions.</p>
|
||
<p>L&#8217;idée finale est d&#8217;avoir&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li>Un backend spécifique permettant de stocker les <em>principals</em> des
|
||
utilisateurs et des <em><span class="caps">ACE</span></em> (e.g. avec les sets Redis)&nbsp;;</li>
|
||
<li>La liste des principals read et write sur la table des&nbsp;objets.</li>
|
||
</ul>
|
||
<p>C&#8217;est dommage d&#8217;avoir le concept de permissions à deux endroits, mais
|
||
cela permet de connaître rapidement la permission d&#8217;un utilisateur sur
|
||
un objet et également de pouvoir récupérer tous les objets d&#8217;une
|
||
collection pour un utilisateur si celui-ci n&#8217;a pas accès à tous les
|
||
records de la collection, ou toutes les collections du&nbsp;bucket.</p>
|
||
</div>
|
||
</content><category term="code"></category></entry><entry><title>Les problèmes de PGP</title><link href="https://blog.notmyidea.org/les-problemes-de-pgp.html" rel="alternate"></link><published>2015-05-25T00:00:00+02:00</published><updated>2015-05-25T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-25:/les-problemes-de-pgp.html</id><summary type="html"><blockquote>
|
||
<p>Flip a bit in the communication between sender and recipient and they
|
||
will experience decryption or verification errors. How high are the
|
||
chances they will start to exchange the data in the clear rather than
|
||
trying to hunt down the man in the&nbsp;middle?</p>
|
||
<p>&#8212; <a href="http://secushare.org/PGP">http://secushare.org/<span class="caps">PGP</span></a></p>
|
||
</blockquote>
|
||
<p>Une fois …</p></summary><content type="html"><blockquote>
|
||
<p>Flip a bit in the communication between sender and recipient and they
|
||
will experience decryption or verification errors. How high are the
|
||
chances they will start to exchange the data in the clear rather than
|
||
trying to hunt down the man in the&nbsp;middle?</p>
|
||
<p>&#8212; <a href="http://secushare.org/PGP">http://secushare.org/<span class="caps">PGP</span></a></p>
|
||
</blockquote>
|
||
<p>Une fois passé l&#8217;euphorie du &#8220;il faut utiliser <span class="caps">PGP</span> pour l&#8217;ensemble de
|
||
nos communications&#8221;, j&#8217;ai réalisé lors de discussions que <span class="caps">PGP</span> avait
|
||
plusieurs problèmes, parmi&nbsp;ceux-ci:</p>
|
||
<ul>
|
||
<li>Les <em>meta données</em> (y compris le champ &#8220;sujet&#8221; de la conversation)
|
||
sont quand même échangées en clair (il est possible de savoir qu&#8217;un
|
||
message à été échangé entre telle et telle personne, a telle&nbsp;date);</li>
|
||
<li><span class="caps">PGP</span> se base sur un protocole de communication qui est lui non
|
||
chiffré, et il est donc facile de soit se tromper, soit dégrader le
|
||
mode de conversation vers une méthode non&nbsp;chiffrée;</li>
|
||
<li>Il est facile de connaître votre réseau social avec <span class="caps">PGP</span>, puisque
|
||
tout le principe est de signer les clés des personnes dont vous
|
||
validez&nbsp;l&#8217;identité;</li>
|
||
<li>En cas de fuite de votre clé privée, tous les messages que vous avez
|
||
chiffrés avec elle sont compromis. On dit que <span class="caps">PGP</span> ne fournit pas de
|
||
<em>forward secrecy</em>;</li>
|
||
<li>La découverte de la clé de pairs se passe souvent <em>en clair</em>, sans
|
||
utiliser une connexion &#8220;sécurisée&#8221; (<span class="caps">HTTPS</span>). Tout le monde peut donc
|
||
voir ces échanges et savoir de qui vous cherchez la&nbsp;clé;</li>
|
||
<li>Les discussions de groupes sont très difficiles: il faut chiffrer
|
||
pour chacun des destinataires (ou que ceux-ci partagent une paire de&nbsp;clés).</li>
|
||
</ul>
|
||
<p>Je suis en train de creuser à propos les alternatives à <span class="caps">PGP</span>, par exemple
|
||
<a href="https://pond.imperialviolet.org/">Pond</a>, qui lui ne construit pas par
|
||
dessus un standard déjà établi, et donc n&#8217;hérite pas de ses défauts
|
||
(mais pas non plus de son réseau déjà&nbsp;établi).</p>
|
||
<p>En attendant, quelques bonnes pratiques sur <span class="caps">PGP</span>&nbsp;;)</p>
|
||
<h2 id="bonnes-pratiques">Bonnes&nbsp;pratiques</h2>
|
||
<p>Il est en fait assez facile d&#8217;utiliser <span class="caps">PGP</span> de travers. Riseup à fait <a href="https://help.riseup.net/en/security/message-security/openpgp/best-practices">un
|
||
excellent
|
||
guide</a>
|
||
qui explique comment configurer son installation&nbsp;correctement.</p>
|
||
<ul>
|
||
<li>J&#8217;en ai déjà parlé, mais il faut absolument choisir des phrases de
|
||
passes suffisamment longues. Pas facile de les retenir, mais
|
||
indispensable. Vous pouvez aussi avoir un document chiffré avec une
|
||
clé que vous ne mettez jamais en ligne, qui contiens ces phrases de
|
||
passe, au cas ou vous les&nbsp;oubliez.</li>
|
||
<li>Générez des clés <span class="caps">RSA</span> de 4096 bits, en utilisant&nbsp;sha512;</li>
|
||
<li>Il faut utiliser une date d&#8217;expiration de nos clés suffisamment
|
||
proche (2 ans). Il est possible de repousser cette date si
|
||
nécessaire, par la&nbsp;suite.</li>
|
||
</ul>
|
||
<p>Parmi les choses les plus frappantes que j&#8217;ai&nbsp;rencontrées:</p>
|
||
<ul>
|
||
<li>Utiliser le <em>flag</em> –hidden-recipient avec <span class="caps">PGP</span> pour ne pas dévoiler
|
||
qui est le destinataire du&nbsp;message;</li>
|
||
<li>Ne pas envoyer les messages de brouillons sur votre serveur, ils le
|
||
seraient en clair&nbsp;!;</li>
|
||
<li>Utilisez <span class="caps">HPKS</span> pour communiquer avec les serveurs de clés, sinon tout
|
||
le trafic est en&nbsp;clair.</li>
|
||
</ul>
|
||
<p>Le <a href="https://bitmask.net/">projet Bitmask</a> vise lui à rendre les outils
|
||
de chiffrement d&#8217;échanges de messages et de <span class="caps">VPN</span> simples à utiliser,
|
||
encore quelque chose à&nbsp;regarder.</p>
|
||
<p>Enfin bref, y&#8217;a du&nbsp;taf.</p></content><category term="code"></category></entry><entry><title>Travail et créativité</title><link href="https://blog.notmyidea.org/travail-et-creativite.html" rel="alternate"></link><published>2015-05-21T00:00:00+02:00</published><updated>2015-05-21T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-21:/travail-et-creativite.html</id><summary type="html"><hr>
|
||
<blockquote>
|
||
<p>Low-risk, low-pressure, and love: The 3 rules of side projects.
|
||
&#8212; <a href="https://open.bufferapp.com/side-projects-creative-hobbies/">The science of side&nbsp;projects</a></p>
|
||
</blockquote>
|
||
<p>Je ne m&#8217;étais jamais fais la remarque, mais les projets dont je suis le
|
||
plus fier sont effectivement des <em>side projects</em>. Des projets que j&#8217;ai
|
||
commencé parce que j&#8217;en avais l&#8217;envie …</p></summary><content type="html"><hr>
|
||
<blockquote>
|
||
<p>Low-risk, low-pressure, and love: The 3 rules of side projects.
|
||
&#8212; <a href="https://open.bufferapp.com/side-projects-creative-hobbies/">The science of side&nbsp;projects</a></p>
|
||
</blockquote>
|
||
<p>Je ne m&#8217;étais jamais fais la remarque, mais les projets dont je suis le
|
||
plus fier sont effectivement des <em>side projects</em>. Des projets que j&#8217;ai
|
||
commencé parce que j&#8217;en avais l&#8217;envie et le temps, qui n&#8217;étaient bien
|
||
souvent que des envies&nbsp;passagères.</p>
|
||
<p>Il est arrivé que quelqu&#8217;un m&#8217;ait demandé de le faire, et que j&#8217;y prenne
|
||
du plaisir, ou que je le fasse simplement pour moi et que d&#8217;autres y
|
||
trouvent leur compte, mais il s&#8217;agit nécessairement de projets non
|
||
<em>commandités</em> par&nbsp;l&#8217;extérieur.</p>
|
||
<p>Encore un signal dans la direction du travailler moins, cette fois ci
|
||
pour être plus&nbsp;créatif.</p>
|
||
<p><img alt="Soupa'Soups." src="/images/soupasoups.jpg"></p></content><category term="journal"></category></entry><entry><title>Simplifier les preuves d’identités</title><link href="https://blog.notmyidea.org/simplifier-les-preuves-didentites.html" rel="alternate"></link><published>2015-05-11T00:00:00+02:00</published><updated>2015-05-11T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-11:/simplifier-les-preuves-didentites.html</id><summary type="html">
|
||
<ul>
|
||
<li>headline<br>
|
||
Qu&#8217;est-ce que Keybase.io et comment essayent-ils de simplifier la
|
||
création de preuves&nbsp;d&#8217;identité.</li>
|
||
</ul>
|
||
<p>L&#8217;un des problèmes non réellement résolu actuellement quant au
|
||
chiffrement des échanges est lié à l&#8217;authenticité des clés. Si quelqu&#8217;un
|
||
décide de publier une clé en mon nom, et en …</p></summary><content type="html">
|
||
<ul>
|
||
<li>headline<br>
|
||
Qu&#8217;est-ce que Keybase.io et comment essayent-ils de simplifier la
|
||
création de preuves&nbsp;d&#8217;identité.</li>
|
||
</ul>
|
||
<p>L&#8217;un des problèmes non réellement résolu actuellement quant au
|
||
chiffrement des échanges est lié à l&#8217;authenticité des clés. Si quelqu&#8217;un
|
||
décide de publier une clé en mon nom, et en utilisant mon adresse email,
|
||
cela lui est assez&nbsp;facile.</p>
|
||
<p>Il est donc nécessaire d&#8217;avoir des moyens de prouver que la clé publique
|
||
que j&#8217;utilise est réellement la&nbsp;mienne.</p>
|
||
<p>Traditionnellement, il est nécessaire de faire signer ma clé publique
|
||
par d&#8217;autres personnes, via une rencontre en personne ou des échanges
|
||
hors du réseau. C&#8217;est par exemple ce qui est réalisé lors des <a href="https://fr.wikipedia.org/wiki/Key_signing_party">Key
|
||
Signing parties</a>.</p>
|
||
<p>Une manière simple d&#8217;effectuer ces vérifications serait, en plus de
|
||
donner son adresse email, sa signature de clé, ou a minima de donner un
|
||
mot clé pour valider que les échanges proviennent bien de la bonne&nbsp;personne.</p>
|
||
<p><span class="caps">PGP</span> propose un mécanisme de signature des clés d&#8217;autrui, une fois celles
|
||
ci validées, ce qui permet de placer sa confiance dans les signataires
|
||
de la&nbsp;clé.</p>
|
||
<p><a href="https://keybase.io">Keybase.io</a> est un service qui vise à rendre la
|
||
création de ces preuves plus facile, en partant du principe qu&#8217;il est
|
||
possible d&#8217;utiliser différents moyens afin de prouver l&#8217;identité des
|
||
personnes. Par exemple, leurs comptes Twitter, GitHub ou leurs noms de
|
||
domaines. De la même manière qu&#8217;il est possible de signer (valider) les
|
||
clés de nos amis, il est possible de les &#8220;tracker&#8221; selon le jargon de&nbsp;keybase.</p>
|
||
<p>Donc, en somme, <em>Keybase.io</em> est un annuaire, qui tente de rendre plus
|
||
facile la création de preuves.&nbsp;Bien.</p>
|
||
<h2 id="quelques-points-dombre">Quelques points&nbsp;d&#8217;ombre</h2>
|
||
<p>Il s&#8217;agit d&#8217;une <em>startup</em> américaine, domiciliée dans le Delaware, qui
|
||
se trouve être un des paradis fiscaux qui <a href="https://fr.wikipedia.org/wiki/Delaware">est connu pour être un
|
||
paradis fiscal au coeur même des
|
||
États-Unis</a>. Je ne veux pas
|
||
faire de raccourcis trop rapides, bien évidemment, alors <a href="https://github.com/keybase/keybase-issues/issues/1569">j&#8217;ai ouvert un
|
||
ticket sur GitHub pour en savoir
|
||
plus</a> (après
|
||
tout, le fait d&#8217;être un paradis fiscal permet peut-être d&#8217;échapper à
|
||
certaines lois sur la requêtes de données). D&#8217;autant plus étonnant, la
|
||
startup n&#8217;a pour l&#8217;instant <a href="https://github.com/keybase/keybase-issues/issues/788">pas de <em>business
|
||
model</em></a> (ce qui en
|
||
un sens est assez rassurant, même si on peut se poser la question de
|
||
pourquoi faire une startup dans ces cas&nbsp;là).</p>
|
||
<p>Le service (bien qu&#8217;en Alpha), n&#8217;est pas mis à disposition sous licence
|
||
libre, ce qui pour l&#8217;instant empêche quiconque de créer son propre
|
||
serveur Keybase. <a href="https://github.com/keybase/">Une partie des composants, cependant, le sont (open
|
||
source)</a>.</p>
|
||
<p>J&#8217;ai du mal à croire en des initiatives qui veulent sauver le monde,
|
||
mais dans leur coin, je ne comprends pas pourquoi il n&#8217;y à pas de
|
||
documentation sur comment monter son propre serveur, ou comment les
|
||
aider à travailler sur la fédération. Mais bon, c&#8217;est pour l&#8217;instant une
|
||
initiative encore fraîche, et je lui laisse le bénéfice du&nbsp;doute.</p>
|
||
<p>Sur le long terme, une infrastructure comme <em>Keybase.io</em>, devra
|
||
évidemment être
|
||
<a href="https://github.com/keybase/keybase-issues/issues/162">distribuée</a>.</p>
|
||
<blockquote>
|
||
<p>We&#8217;ve been talking about a total decentralization, but we have to
|
||
solve a couple things, synchronization in particular. Right now
|
||
someone can mirror us and a client can trust a mirror just as easily
|
||
as the server at keybase.io, but there needs to be a way of announcing
|
||
proofs to any server and having them cooperate with each other. We&#8217;d
|
||
be so happy to get this&nbsp;right.</p>
|
||
<p>&#8212; <a href="http://chris.beams.io/posts/keybase/">Chris Coyne, co-founder of&nbsp;Keybase</a></p>
|
||
</blockquote>
|
||
<p>Afin de se &#8220;passer&#8221; de leur service centralisé, les preuves générées
|
||
(qui sont la force du système qu&#8217;ils mettent en place) pourraient être
|
||
exportées sur des serveurs de clés existants. C&#8217;est quelque chose
|
||
<a href="https://github.com/keybase/keybase-issues/issues/890">qu&#8217;ils souhaitent réaliser
|
||
.</a>.</p>
|
||
<p>Bref, une initiative quand même importante et utile, même si elle
|
||
soulève des questions qui méritent qu&#8217;on s&#8217;y attarde un&nbsp;brin.</p>
|
||
<p>Par ailleurs, <a href="https://leap.se/nicknym">d&#8217;autres projets qui visent des objectifs
|
||
similaires</a> existent, via le projet <span class="caps">LEAP</span>, mais
|
||
je n&#8217;ai pas encore&nbsp;creusé.</p></content><category term="code"></category></entry><entry><title>Phrases de passe et bonnes pratiques</title><link href="https://blog.notmyidea.org/phrases-de-passe-et-bonnes-pratiques.html" rel="alternate"></link><published>2015-05-09T00:00:00+02:00</published><updated>2015-05-09T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-09:/phrases-de-passe-et-bonnes-pratiques.html</id><summary type="html">
|
||
<ul>
|
||
<li>headline<br>
|
||
Communiquer de manière chiffrée n&#8217;est pas aisée, et nécessite de
|
||
mémoriser des phrases de passes complexes. Comment s&#8217;en sortir&nbsp;?</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Au contraire des autres mots de passe, les mots de passe
|
||
cryptographiques ont specifiquement besoin d&#8217;être longs et extremement
|
||
difficiles à deviner. La raison est qu&#8217;un …</p></blockquote></summary><content type="html">
|
||
<ul>
|
||
<li>headline<br>
|
||
Communiquer de manière chiffrée n&#8217;est pas aisée, et nécessite de
|
||
mémoriser des phrases de passes complexes. Comment s&#8217;en sortir&nbsp;?</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>Au contraire des autres mots de passe, les mots de passe
|
||
cryptographiques ont specifiquement besoin d&#8217;être longs et extremement
|
||
difficiles à deviner. La raison est qu&#8217;un ordinateur (ou un cluster de
|
||
plusieurs ordinateurs) peut être programmé pour faire des trillions
|
||
d&#8217;essais de manière automatique. Si le mot de passe choisi est trop
|
||
faible ou construit d&#8217;une manière trop prédictible, cette attaque par
|
||
la force pourrait se revéler fructueuse en essayant toutes les&nbsp;possibilités.</p>
|
||
<p>&#8212; <a href="https://www.eff.org/wp/defending-privacy-us-border-guide-travelers-carrying-digital-devices">The Electronic Frontier
|
||
Foundation</a>
|
||
(traduction de mon&nbsp;fait)</p>
|
||
</blockquote>
|
||
<p>Comprendre les concepts et l&#8217;écosystème qui permettent d&#8217;avoir une vie
|
||
numérique chiffrée n&#8217;est pas quelque chose d&#8217;aisé.
|
||
<a href="https://emailselfdefense.fsf.org/fr/">Plusieurs</a>
|
||
<a href="http://www.controle-tes-donnees.net/outils/GnuPG.html">guides</a> ont été
|
||
écrits à ce propos, et pour autant je me rends compte que naïvement il
|
||
est possible de mal utiliser les outils&nbsp;existants.</p>
|
||
<blockquote>
|
||
<p>Utilisez un <em>bon</em> mot de passe pour votre session utilisateur et une
|
||
<em>bonne</em> phrase de passe pour proteger votre clé privée. Cette phrase
|
||
de passe est la partie la plus fragile de tout le&nbsp;système.</p>
|
||
<p>&#8212; La page de manuel de <span class="caps">GPG</span>.</p>
|
||
</blockquote>
|
||
<p>Une phrase de passe&nbsp;devrait:</p>
|
||
<ul>
|
||
<li>Être suffisamment longue pour être difficile à&nbsp;deviner;</li>
|
||
<li>Ne pas être une citation connue (littérature, livres sacrés&nbsp;etc);</li>
|
||
<li>Difficile à deviner même pour vos&nbsp;proches;</li>
|
||
<li>Facile à se souvenir et à&nbsp;taper;</li>
|
||
<li>être unique et non partagée entre différents sites / applications&nbsp;etc.</li>
|
||
</ul>
|
||
<p>Une des techniques consiste à utiliser des mots du dictionnaire,
|
||
sélectionnés de manière aléatoire, puis&nbsp;modifiés.</p>
|
||
<p><img alt="Trough 20 years of effort, we've succesfully trained everyone to use passwords that are hard for humans to remember, but easy for computers to guess" src="https://imgs.xkcd.com/comics/password_strength.png"></p>
|
||
<p>Micah Lee <a href="https://github.com/micahflee/passphrases">travaille également sur un
|
||
outil</a> qui vise à rendre la
|
||
mémorisation des phrases de passe plus aisée, de par leur répétition
|
||
avec des pauses de plus en plus&nbsp;longues.</p>
|
||
<p>Oui, ce n&#8217;est pas aussi simple que ce qu&#8217;il y parait. Pour ma part, j&#8217;ai
|
||
une copie en local de mes clés, dans un fichier chiffré avec une autre
|
||
clé que j&#8217;ai généré pour l&#8217;occasion et que je ne partagerait pas. J&#8217;ai
|
||
par ailleurs <a href="https://github.com/jamessan/vim-gnupg">configuré</a> mon
|
||
éditeur de texte pour pouvoir chiffrer les documents textes par&nbsp;défaut.</p>
|
||
<p>J&#8217;ai donc regénéré une nouvelle fois mes clés de travail et
|
||
personnelles, en utilisant des phrases de passe plus&nbsp;complexes.</p>
|
||
<p>Reste encore la question de la sauvegarde de ces clés privées de manière
|
||
chiffrée, que je n&#8217;ai pas encore résolue. Bref, tout cela me semble bien
|
||
compliqué pour réussir à l&#8217;expliquer à des novices, qui pour certains ne
|
||
sont même pas sur de l&#8217;intérêt de la&nbsp;chose.</p></content><category term="code"></category></entry><entry><title>Chiffrement</title><link href="https://blog.notmyidea.org/chiffrement.html" rel="alternate"></link><published>2015-05-08T00:00:00+02:00</published><updated>2015-05-08T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-08:/chiffrement.html</id><summary type="html">
|
||
<ul>
|
||
<li>headline<br>
|
||
Face a la surveillance généralisée, une seule solution, le
|
||
chiffrement de nos données et&nbsp;communications.</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>En france, depuis le 5 Mai 2015, il est possible au Premier Ministre
|
||
de surveiller massivement et sans contrôle la population&nbsp;française.</p>
|
||
<p>le projet de loi n&#8217;a pas été significativement amendé en séance …</p></blockquote></summary><content type="html">
|
||
<ul>
|
||
<li>headline<br>
|
||
Face a la surveillance généralisée, une seule solution, le
|
||
chiffrement de nos données et&nbsp;communications.</li>
|
||
</ul>
|
||
<blockquote>
|
||
<p>En france, depuis le 5 Mai 2015, il est possible au Premier Ministre
|
||
de surveiller massivement et sans contrôle la population&nbsp;française.</p>
|
||
<p>le projet de loi n&#8217;a pas été significativement amendé en séance
|
||
mi-avril, et ses dispositions dangereuses ont été conservées&nbsp;:</p>
|
||
<ul>
|
||
<li>Élargissement des finalités du renseignement, permettant une
|
||
<strong>potentielle mise sous surveillance de pans entiers de la vie
|
||
politique, syndicale, militante</strong>, mais aussi économique,
|
||
scientifique, etc.&nbsp;;</li>
|
||
<li>Légalisation massive de pratiques illégales des services de
|
||
renseignement et <strong>introduction de techniques de surveillance de
|
||
masse des communications électroniques</strong>&nbsp;;</li>
|
||
<li><strong>Absence de contrôle réel et indépendant</strong> a priori par la future
|
||
<span class="caps">CNCTR</span>, et recours des citoyens illusoires&nbsp;;</li>
|
||
</ul>
|
||
<p>&#8212; <a href="https://www.laquadrature.net/fr/lassemblee-nationale-vote-la-surveillance-de-masse-des-citoyens-francais">La Quadrature du Net - L&#8217;Assemblée nationale vote la surveillance
|
||
de masse des citoyens français&nbsp;!</a></p>
|
||
</blockquote>
|
||
<p>Je m&#8217;étonne que <a href="https://fr.wikipedia.org/wiki/R%C3%A9v%C3%A9lations_d%27Edward_Snowden">les révélations d&#8217;Edward
|
||
Snowden</a>
|
||
— qui ont démontré que la plupart des communications électroniques et
|
||
téléphoniques pouvaient être scrutés par la <span class="caps">NSA</span>, l&#8217;agence de sécurité
|
||
Américaine) — ne fassent pas plus de remous que&nbsp;ça.</p>
|
||
<p>À peine deux années après ces révélations, la France fait passer une loi
|
||
qui légitime cette surveillance de masse, à plus de 77% des voies. Pour
|
||
moi c&#8217;est un signal fort de la perte de valeurs de notre démocratie, et
|
||
à fortiori de ma perte de foi en notre forme de&nbsp;démocratie.</p>
|
||
<p>Notre liberté d&#8217;expression se voit bien évidemment amputée de par la
|
||
surveillance généralisée. Sans avoir nécessairement à cacher mes
|
||
échanges, ce qui est de la sphère privée devrait pouvoir le&nbsp;rester.</p>
|
||
<p>De toute manière, l&#8217;email comme on l&#8217;utilise traditionnellement est une
|
||
hérésie: toutes les parties qui traitent le message peuvent le lire,
|
||
(destinataire, auteur et corps du message entre autres). Il est grand
|
||
temps de rendre les outils de chiffrement plus simples et&nbsp;ergonomiques.</p>
|
||
<p>Je compte&nbsp;donc:</p>
|
||
<ul>
|
||
<li>Organiser des ateliers de sensibilisation aux outils de
|
||
communication, envers mes&nbsp;proches;</li>
|
||
<li>Utiliser la communication chiffrée le plus souvent possible, au
|
||
moins pour rendre le déchiffrement des messages plus longue, &#8220;noyer
|
||
le&nbsp;poisson&#8221;.</li>
|
||
</ul>
|
||
<p>Si vous êtes intéressé(e)s, faites moi signe, je me ferais un plaisir de
|
||
vous expliquer ce qui n&#8217;est pas si complexe et vise à laisser dans la
|
||
sphère privée ce qui devrait l&#8217;être à&nbsp;priori.</p>
|
||
<p>Une manière simple de se protéger est d&#8217;installer Thunderbird avec
|
||
Enigmail et de le configurer correctement. Ce n&#8217;est pas très compliqué
|
||
et permet d&#8217;avoir des échanges chiffrés. <a href="https://emailselfdefense.fsf.org/fr/">Référez vous à ce
|
||
guide</a> pour des instructions pas à&nbsp;pas.</p>
|
||
<p>Je vous invite à aller voir le documentaire Citizen Four, qui passe en
|
||
salles. Si vous ni avez pas accès, vous pouvez le visionner ici, et
|
||
éventuellement faire un don aux auteurs ou associations qui gravitent
|
||
autour (<a href="https://supporters.eff.org/donate">Electronic Fronteer
|
||
Fondation</a>,
|
||
<a href="https://tails.boum.org/contribute/how/donate/index.fr.html">Tails</a>, <a href="https://support.laquadrature.net/">La
|
||
quadrature du net</a> en france ou&nbsp;d&#8217;autres…)</p>
|
||
<p><link href="http://vjs.zencdn.net/4.12/video-js.css" rel="stylesheet"></p>
|
||
<script src="http://vjs.zencdn.net/4.12/video.js"></script>
|
||
<video id="MY_VIDEO_1" class="video-js vjs-default-skin" controls
|
||
preload="auto" width="640" height="264" poster="MY_VIDEO_POSTER.jpg"
|
||
data-setup="{}">
|
||
<source src="https://citizenfour.thecthulhu.com/citizenfour.mp4" type='video/mp4'>
|
||
<p class="vjs-no-js">To view this video please enable JavaScript, and
|
||
consider upgrading to a web browser that <a
|
||
href="http://videojs.com/html5-video-support/" target="_blank">supports
|
||
<span class="caps">HTML5</span>&nbsp;video</a></p>
|
||
</video></content><category term="journal"></category></entry><entry><title>Language</title><link href="https://blog.notmyidea.org/language.html" rel="alternate"></link><published>2015-05-01T00:00:00+02:00</published><updated>2015-05-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-01:/language.html</id><summary type="html"><p>headline : Nos langues peuvent être autant de frontières que de&nbsp;ponts&#8230;</p>
|
||
|
||
<blockquote>
|
||
<p>Nous savons tous que le fait d&#8217;obliger les fonctionnaires
|
||
internationaux, diplomates ou ministres à s&#8217;exprimer dans une langue
|
||
qui n&#8217;est pas la leur équivaut à les placer en situation
|
||
d&#8217;infériorité. <strong>Cela les prive de la …</strong></p></blockquote></summary><content type="html"><p>headline : Nos langues peuvent être autant de frontières que de&nbsp;ponts&#8230;</p>
|
||
|
||
<blockquote>
|
||
<p>Nous savons tous que le fait d&#8217;obliger les fonctionnaires
|
||
internationaux, diplomates ou ministres à s&#8217;exprimer dans une langue
|
||
qui n&#8217;est pas la leur équivaut à les placer en situation
|
||
d&#8217;infériorité. <strong>Cela les prive de la capacité de nuance et de
|
||
raffinement</strong>, ce qui revient à faire des concessions à ceux dont
|
||
c&#8217;est la langue&nbsp;maternelle.</p>
|
||
<p>Aussi nous savons tous que les concepts qui paraissent similaires sont
|
||
souvent différents d&#8217;une civilisation à l&#8217;autre. Les mots expriment
|
||
une culture, une façon de penser et une vision du&nbsp;monde.</p>
|
||
<p>&#8212; M. Boutros Boutros-Ghali, ancien secrétaire général des Nations&nbsp;Unies</p>
|
||
</blockquote>
|
||
<p>Je me surprends à préférer le français pour m&#8217;exprimer au lieu de
|
||
l&#8217;anglais, notamment au niveau des articles non&nbsp;techniques.</p>
|
||
<p>Il y a quelques années, alors que je terminais mes études en Angleterre
|
||
et que je commençais à travailler pour Mozilla, on me proposait de venir
|
||
aux États-Unis, ce que j&#8217;ai refusé parce qu&#8217;exprimer mes points de vue
|
||
de manière fine m&#8217;était trop difficile dans une langue qui n&#8217;était pas
|
||
la&nbsp;mienne.</p>
|
||
<ul>
|
||
<li>Cela me permet de pouvoir tenir des discours avec des positions et
|
||
un argumentaire &#8220;fin&#8221;, ce qui me serait beaucoup plus difficile dans
|
||
une langue que je maitrise&nbsp;moins;</li>
|
||
<li>Sans même parler d&#8217;argumentaire, les mots utilisés dans ma langue
|
||
maternelle me permettent de manœuvrer plus finement et de faire
|
||
passer des idées de manière plus&nbsp;efficace;</li>
|
||
<li>J&#8217;ai l&#8217;impression de pouvoir engager plus facilement avec les gens
|
||
qui m&#8217;entourent géographiquement, par exemple par rapport à la
|
||
communauté technophile / pythoniste&nbsp;francophone.</li>
|
||
<li>Même si mon niveau d&#8217;anglais à progressé, ce n&#8217;est pas
|
||
nécessairement le cas de mes&nbsp;interlocuteurs.</li>
|
||
</ul>
|
||
<p>Par contre, cela nuit clairement à engager avec d&#8217;autres personnes dont
|
||
la langue n&#8217;est pas la mienne, dans tels cas, traduire les contenus
|
||
intéressants vers l&#8217;anglais semble une solution&nbsp;(chronophage).</p></content><category term="journal"></category></entry><entry><title>Service de nuages : La gestion des permissions</title><link href="https://blog.notmyidea.org/service-de-nuages-la-gestion-des-permissions-fr.html" rel="alternate"></link><published>2015-05-01T00:00:00+02:00</published><updated>2015-05-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-05-01:/service-de-nuages-la-gestion-des-permissions-fr.html</id><summary type="html"><p class="first last">Démystification du vocabulaire des permissions et proposition d&#8217;implémentation pour&nbsp;Kinto</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p>Dans le cadre de la création d&#8217;un service de stockage de données personnelles
|
||
(Kinto), la gestion des permissions est un des gros challenges : qui doit avoir
|
||
accès à quoi, et comment le définir&nbsp;?</p>
|
||
<p><strong>tl;dr: Quelques retours sur le vocabulaire des systèmes de permission et sur nos idées pour l&#8217;implementation des permissions dans un stockage&nbsp;générique.</strong></p>
|
||
<div class="section" id="la-problematique">
|
||
<h2>La&nbsp;problématique</h2>
|
||
<p>La problématique est simple : des données sont stockées en ligne, et il
|
||
faut un moyen de pouvoir les partager avec d&#8217;autres&nbsp;personnes.</p>
|
||
<p>En regardant les cas d&#8217;utilisations, on se rend compte qu&#8217;on a plusieurs types
|
||
d&#8217;utilisateurs&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li>les utilisateurs &#8220;finaux&#8221; (vous)&nbsp;;</li>
|
||
<li>les applications qui interagissent en leurs&nbsp;noms.</li>
|
||
</ul>
|
||
<p>Tous les intervenants n&#8217;ont donc pas les mêmes droits : certains doivent
|
||
pouvoir lire, d&#8217;autres écrire, d&#8217;autres encore créer de nouveaux
|
||
enregistrements, et le contrôle doit pouvoir s&#8217;effectuer de manière fine : il
|
||
doit être possible de lire un enregistrement mais pas un autre, par&nbsp;exemple.</p>
|
||
<p>Nous sommes partis du constat que les solutions disponibles n&#8217;apportaient pas
|
||
une réponse satisfaisante à ces&nbsp;besoins.</p>
|
||
</div>
|
||
<div class="section" id="un-probleme-de-vocabulaire">
|
||
<h2>Un problème de&nbsp;vocabulaire</h2>
|
||
<p>Le principal problème rencontré lors des réflexions fût le&nbsp;vocabulaire.</p>
|
||
<p>Voici ci-dessous une explication des différents&nbsp;termes.</p>
|
||
<div class="section" id="le-concept-de-principal">
|
||
<h3>Le concept de « principal&nbsp;»</h3>
|
||
<p>Un <em>principal</em>, en sécurité informatique, est une entité qui peut être
|
||
authentifiée par un système informatique. <a class="footnote-reference" href="#footnote-1" id="footnote-reference-1">[1]</a> En Français il s&#8217;agit
|
||
du « commettant », l&#8217;acteur qui commet l&#8217;action (oui, le terme est conceptuel&nbsp;!)</p>
|
||
<p>Il peut s&#8217;agir aussi bien d&#8217;un individu, d&#8217;un ordinateur, d&#8217;un
|
||
service ou d&#8217;un groupe regroupant l&#8217;une de ces entités, ce qui
|
||
est plus large que le classique « <em>user id</em>&nbsp;».</p>
|
||
<p>Les permissions sont alors associées à ces <em>principals</em>.</p>
|
||
<p>Par exemple, un utilisateur est identifié de manière unique lors de la
|
||
connexion par le système d&#8217;authentification dont le rôle est de
|
||
définir une liste de <em>principals</em> pour l&#8217;utilisateur se&nbsp;connectant.</p>
|
||
<table class="docutils footnote" frame="void" id="footnote-1" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-1">[1]</a></td><td>Pour en savoir plus sur les <em>principals</em> :
|
||
<a class="reference external" href="https://en.wikipedia.org/wiki/Principal_%28computer_security%29">https://en.wikipedia.org/wiki/Principal_%28computer_security%29</a></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="section" id="la-difference-entre-role-et-groupe">
|
||
<h3>La différence entre rôle et&nbsp;groupe</h3>
|
||
<p>De but en blanc, il n&#8217;est pas évident de définir précisément la
|
||
différence entre ces deux concepts qui permettent d&#8217;associer
|
||
des permissions à un groupe de <em>principals</em>. <a class="footnote-reference" href="#footnote-2" id="footnote-reference-2">[2]</a></p>
|
||
<p>La différence est principalement sémantique. Mais on peut y voir une
|
||
différence dans la « direction » de la relation entre les deux&nbsp;concepts.</p>
|
||
<ul class="simple">
|
||
<li>Un rôle est une liste de permissions que l&#8217;on associe à un <em>principal</em>.</li>
|
||
<li>Un groupe est une liste de <em>principals</em> que l&#8217;on peut associer à une&nbsp;permission.</li>
|
||
</ul>
|
||
<table class="docutils footnote" frame="void" id="footnote-2" rules="none">
|
||
<colgroup><col class="label" /><col /></colgroup>
|
||
<tbody valign="top">
|
||
<tr><td class="label"><a class="fn-backref" href="#footnote-reference-2">[2]</a></td><td>Plus d&#8217;informations :
|
||
<a class="reference external" href="http://stackoverflow.com/questions/7770728/group-vs-role-any-real-difference">http://stackoverflow.com/questions/7770728/group-vs-role-any-real-difference</a></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="section" id="la-difference-entre-permission-acl-ace">
|
||
<h3>La différence entre permission, <span class="caps">ACL</span>, <span class="caps">ACE</span></h3>
|
||
<blockquote class="epigraph">
|
||
<p>Une <span class="caps">ACL</span> est une liste d’Access Control Entry (<span class="caps">ACE</span>) ou entrée de contrôle d&#8217;accès
|
||
donnant ou supprimant des droits d&#8217;accès à une personne ou un&nbsp;groupe.</p>
|
||
<p class="attribution">&mdash;<a class="reference external" href="https://fr.wikipedia.org/wiki/Access_Control_List">https://fr.wikipedia.org/wiki/Access_Control_List</a></p>
|
||
</blockquote>
|
||
<p>Je dirais même plus, dans notre cas, « à un <em>principal</em> ». Par&nbsp;exemple:</p>
|
||
<div class="highlight"><pre><span></span>create_record: alexis,remy,tarek
|
||
</pre></div>
|
||
<p>Cet <span class="caps">ACE</span> donne la permission <tt class="docutils literal">create</tt> sur l&#8217;objet <tt class="docutils literal">record</tt> aux
|
||
utilisateurs Tarek, Rémy et&nbsp;Alexis.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="la-delegation-de-permissions">
|
||
<h2>La délégation de&nbsp;permissions</h2>
|
||
<p>Imaginez l&#8217;exemple suivant, où un utilisateur stocke deux types de données en
|
||
ligne&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li>des contacts&nbsp;;</li>
|
||
<li>une liste de tâches à faire qu&#8217;il peut associer à ses&nbsp;contacts.</li>
|
||
</ul>
|
||
<p>L&#8217;utilisateur a tous les droits sur ses&nbsp;données.</p>
|
||
<p>Cependant il utilise deux applications qui doivent elles avoir un accès restreint&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li>une application de gestion des contacts à qui il souhaite déléguer
|
||
la gestion intégrale de ses contacts : <tt class="docutils literal">contacts:write</tt> ;</li>
|
||
<li>une application de gestion des tâches à qui il souhaite déléguer la
|
||
gestion des tâches : <tt class="docutils literal">contacts:read tasks:write</tt></li>
|
||
</ul>
|
||
<p>Il souhaite que son application de contacts ne puisse pas accéder à
|
||
ses tâches et que son application de tâches ne puisse pas modifier ses
|
||
contacts existants, juste éventuellement en créer de&nbsp;nouveaux.</p>
|
||
<p>Il lui faut donc un moyen de déléguer certains de ses droits à un tiers&nbsp;(l&#8217;application).</p>
|
||
<p>C&#8217;est précisément le rôle des <a class="reference external" href="http://tools.ietf.org/html/rfc6749#page-23">scopes OAuth2</a>.</p>
|
||
<p>Lors de la connexion d&#8217;un utilisateur, une fenêtre lui demande quels
|
||
accès il veut donner à l&#8217;application qui va agir en son&nbsp;nom.</p>
|
||
<p>Le service aura ensuite accès à ces <em>scopes</em> en regardant le jeton
|
||
d&#8217;authentification utilisé. Cette information doit être
|
||
considérée comme une entrée utilisateur (c&#8217;est à dire qu&#8217;on ne peut
|
||
pas lui faire confiance). Il s&#8217;agit de ce que l&#8217;utilisateur&nbsp;souhaite.</p>
|
||
<p>Or, il est également possible que l&#8217;utilisateur n&#8217;ait pas accès aux données
|
||
qu&#8217;il demande. Le service doit donc utiliser deux niveaux de permissions :
|
||
celles de l&#8217;utilisateur, et celles qui ont été déléguées à&nbsp;l&#8217;application.</p>
|
||
</div>
|
||
<div class="section" id="espace-de-noms">
|
||
<h2>Espace de&nbsp;noms</h2>
|
||
<p>Dans notre implémentation initiale de <em>Kinto</em> (notre service de stockage en
|
||
construction), l&#8217;espace de nom était implicite : les données stockées étaient
|
||
nécessairement celles de l&#8217;utilisateur&nbsp;connecté.</p>
|
||
<p>Les données d&#8217;un utilisateur étaient donc cloisonnées et impossible à&nbsp;partager.</p>
|
||
<p>L&#8217;utilisation d&#8217;espaces de noms est une manière simple de gérer le partage des&nbsp;données.</p>
|
||
<p>Nous avons choisi de reprendre le modèle de GitHub et de Bitbucket, qui
|
||
utilisent les « organisations » comme espaces de&nbsp;noms.</p>
|
||
<p>Dans notre cas, il est possible de créer des &#8220;buckets&#8221;, qui correspondent à ces
|
||
espaces de noms. Un bucket est un conteneur de collections et de groupes&nbsp;utilisateurs.</p>
|
||
<p>Les ACLs sur ces collections peuvent être attribuées à certains groupes du
|
||
<em>bucket</em> ainsi qu&#8217;à d&#8217;autres <em>principals</em>&nbsp;directement.</p>
|
||
</div>
|
||
<div class="section" id="notre-proposition-d-api">
|
||
<h2>Notre proposition d&#8217;<span class="caps">API</span></h2>
|
||
<div class="section" id="les-objets-manipules">
|
||
<h3>Les objets&nbsp;manipulés</h3>
|
||
<p>Pour mettre en place la gestion des permissions, nous avons identifié les
|
||
objets suivants&nbsp;:</p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="23%" />
|
||
<col width="77%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Objet</th>
|
||
<th class="head">Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td><strong>bucket</strong></td>
|
||
<td>On peut les voir comme des espaces de noms. Ils
|
||
permettent d&#8217;avoir différentes collections portant
|
||
le même nom mais stockées dans différents <em>buckets</em> de
|
||
manière à ce que les données soient distinctes.</td>
|
||
</tr>
|
||
<tr><td><strong>collection</strong></td>
|
||
<td>Une liste d&#8217;enregistrements.</td>
|
||
</tr>
|
||
<tr><td><strong>record</strong></td>
|
||
<td>Un enregistrement d&#8217;une collection.</td>
|
||
</tr>
|
||
<tr><td><strong>group</strong></td>
|
||
<td>Un groupe de commetants (« <em>principals</em> »).</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Pour la définition des ACLs, il y a une hiérarchie et les objets « héritent » des
|
||
ACLs de leur parents&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span> +---------------+
|
||
| Bucket |
|
||
+---------------+
|
||
+-----&gt;+ - id +&lt;---+
|
||
| | - permissions | |
|
||
| +---------------+ |
|
||
| |
|
||
| |
|
||
| |
|
||
| |
|
||
| |
|
||
+---+-----------+ +------+---------+
|
||
| Collection | | Group |
|
||
+---------------+ +----------------+
|
||
| - id | | - id |
|
||
| - permissions | | - members |
|
||
+------+--------+ | - permissions |
|
||
^ +----------------+
|
||
|
|
||
|
|
||
+------+---------+
|
||
| Record |
|
||
+----------------+
|
||
| - id |
|
||
| - data |
|
||
| - permissions |
|
||
+----------------+
|
||
</pre></div>
|
||
</div>
|
||
<div class="section" id="les-permissions">
|
||
<h3>Les&nbsp;permissions</h3>
|
||
<p>Pour chacun de ces objets nous avons identifié les permissions suivantes&nbsp;:</p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="23%" />
|
||
<col width="77%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Permission</th>
|
||
<th class="head">Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td><strong>read</strong></td>
|
||
<td>La permission de lire le contenu de
|
||
l&#8217;objet et de ses sous-objets.</td>
|
||
</tr>
|
||
<tr><td><strong>write</strong></td>
|
||
<td>La permission de modifier et
|
||
d&#8217;administrer un objet et ses sous-
|
||
objets. La permission <em>write</em> permet la
|
||
lecture, modification et suppression
|
||
d&#8217;un objet ainsi que la gestion de ses
|
||
permissions.</td>
|
||
</tr>
|
||
<tr><td><strong>create</strong></td>
|
||
<td>La permission de créer le sous-objet
|
||
spécifié. Par exemple:
|
||
<tt class="docutils literal">collections:create</tt></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>À chaque permission spécifiée sur un objet est associée une liste de
|
||
<em>principals</em>.</p>
|
||
<p>Dans le cas de la permission <tt class="docutils literal">create</tt> on est obligé de spécifier
|
||
l&#8217;objet enfant en question car un objet peut avoir plusieurs types
|
||
d&#8217;enfants. Par exemple : <tt class="docutils literal">collections:create</tt>, <tt class="docutils literal">groups:create</tt>.</p>
|
||
<p>Nous n&#8217;avons pour l&#8217;instant pas de permission pour <cite>delete</cite> et <cite>update</cite>,
|
||
puisque nous n&#8217;avons pas trouvé de cas d&#8217;utilisation qui les nécessitent.
|
||
Quiconque avec le droit d&#8217;écriture peut donc supprimer un&nbsp;enregistrement.</p>
|
||
<p>Les permissions d&#8217;un objet sont héritées de son parent. Par exemple,
|
||
un enregistrement créé dans une collection accessible à tout le monde
|
||
en lecture sera lui aussi accessible à tout le&nbsp;monde.</p>
|
||
<p>Par conséquent, les permissions sont cumulées. Autrement dit, il n&#8217;est pas
|
||
possible qu&#8217;un objet ait des permissions plus restrictives que son&nbsp;parent.</p>
|
||
<p>Voici la liste exhaustive des permissions&nbsp;:</p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="21%" />
|
||
<col width="32%" />
|
||
<col width="47%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Objet</th>
|
||
<th class="head">Permissions associées</th>
|
||
<th class="head">Commentaire</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td>Configuration
|
||
(.ini)</td>
|
||
<td><cite>buckets:create</cite></td>
|
||
<td>Les <em>principals</em> ayant le droit
|
||
de créer un bucket sont définis
|
||
dans la configuration du serveur.
|
||
(<em>ex. utilisateurs authentifiés</em>)</td>
|
||
</tr>
|
||
<tr><td rowspan="4"><tt class="docutils literal">bucket</tt></td>
|
||
<td><cite>write</cite></td>
|
||
<td>C&#8217;est en quelque sorte le droit
|
||
d&#8217;administration du <em>bucket</em>.</td>
|
||
</tr>
|
||
<tr><td><cite>read</cite></td>
|
||
<td>C&#8217;est le droit de lire le contenu
|
||
de tous les objets du <em>bucket</em>.</td>
|
||
</tr>
|
||
<tr><td><cite>collections:create</cite></td>
|
||
<td>Permission de créer des
|
||
collections dans le <em>bucket</em>.</td>
|
||
</tr>
|
||
<tr><td><cite>groups:create</cite></td>
|
||
<td>Permission de créer des groupes
|
||
dans le <em>bucket</em>.</td>
|
||
</tr>
|
||
<tr><td rowspan="3"><tt class="docutils literal">collection</tt></td>
|
||
<td><cite>write</cite></td>
|
||
<td>Permission d&#8217;administrer tous les
|
||
objets de la collection.</td>
|
||
</tr>
|
||
<tr><td><cite>read</cite></td>
|
||
<td>Permission de consulter tous les
|
||
objets de la collection.</td>
|
||
</tr>
|
||
<tr><td><cite>records:create</cite></td>
|
||
<td>Permission de créer des nouveaux
|
||
enregistrement dans la collection.</td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal">record</tt></td>
|
||
<td><cite>write</cite></td>
|
||
<td>Permission de modifier ou de
|
||
partager l&#8217;enregistrement.</td>
|
||
</tr>
|
||
<tr><td><cite>read</cite></td>
|
||
<td>Permission de consulter
|
||
l&#8217;enregistrement.</td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal">group</tt></td>
|
||
<td><cite>write</cite></td>
|
||
<td>Permission d&#8217;administrer le
|
||
groupe</td>
|
||
</tr>
|
||
<tr><td><cite>read</cite></td>
|
||
<td>Permission de consulter les
|
||
membres du groupe.</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="section" id="les-principals">
|
||
<h3>Les « <em>principals</em>&nbsp;»</h3>
|
||
<p>Les acteurs se connectant au service de stockage peuvent&nbsp;s&#8217;authentifier.</p>
|
||
<p>Ils reçoivent alors une liste de <em>principals</em>&nbsp;:</p>
|
||
<ul class="simple">
|
||
<li><tt class="docutils literal">Everyone</tt>: le <em>principal</em> donné à tous les acteurs (authentifiés ou pas)&nbsp;;</li>
|
||
<li><tt class="docutils literal">Authenticated</tt>: le <em>principal</em> donné à tous les acteurs authentifiés&nbsp;;</li>
|
||
<li>un <em>principal</em> identifiant l&#8217;acteur, par exemple <tt class="docutils literal">fxa:32aa95a474c984d41d395e2d0b614aa2</tt></li>
|
||
</ul>
|
||
<p>Afin d&#8217;éviter les collisions d&#8217;identifiants, le <em>principal</em> de l&#8217;acteur dépend
|
||
de son type d&#8217;authentification (<tt class="docutils literal">system</tt>, <tt class="docutils literal">basic</tt>, <tt class="docutils literal">ipaddr</tt>, <tt class="docutils literal">hawk</tt>,
|
||
<tt class="docutils literal">fxa</tt>) et de son identifiant (unique par&nbsp;acteur).</p>
|
||
<p>En fonction du <em>bucket</em> sur lequel se passe l&#8217;action, les groupes dont
|
||
fait partie l&#8217;utilisateur sont également ajoutés à sa liste de
|
||
<tt class="docutils literal">principals</tt>. <tt class="docutils literal">group:moderators</tt> par&nbsp;exemple.</p>
|
||
<p>Ainsi, si Bob se connecte avec <em>Firefox Accounts</em> sur le <em>bucket</em>
|
||
<tt class="docutils literal">servicedenuages_blog</tt> dans lequel il fait partie du groupe
|
||
<tt class="docutils literal">moderators</tt>, il aura la liste de <em>principals</em> suivante :
|
||
<tt class="docutils literal">Everyone, Authenticated, fxa:32aa95a474c984d41d395e2d0b614aa2, group:moderators</tt></p>
|
||
<p>Il est donc possible d&#8217;assigner une permission à Bob en utilisant l&#8217;un de
|
||
ces quatre <em>principals</em>.</p>
|
||
<div class="admonition note">
|
||
<p class="first admonition-title">Note</p>
|
||
<p class="last">Le <em>principal</em> <tt class="docutils literal">&lt;userid&gt;</tt> dépend du <em>back-end</em> d&#8217;authentification (e.g.
|
||
<tt class="docutils literal">github:leplatrem</tt>).</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="quelques-exemples">
|
||
<h3>Quelques&nbsp;exemples</h3>
|
||
<p><strong>Blog</strong></p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="35%" />
|
||
<col width="18%" />
|
||
<col width="46%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Objet</th>
|
||
<th class="head">Permissions</th>
|
||
<th class="head">Principals</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td><tt class="docutils literal">bucket:blog</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;blog</span> owner id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal">collection:articles</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal">group:moderators</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">read</tt></td>
|
||
<td><tt class="docutils literal">Everyone</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">record:569e28r98889</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;co-author</span> id&gt;</tt></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Wiki</strong></p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="35%" />
|
||
<col width="18%" />
|
||
<col width="46%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Object</th>
|
||
<th class="head">Permissions</th>
|
||
<th class="head">Principals</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td><tt class="docutils literal">bucket:wiki</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;wiki</span> administrator id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal">collection:articles</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal">Authenticated</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">read</tt></td>
|
||
<td><tt class="docutils literal">Everyone</tt></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Sondages</strong></p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="34%" />
|
||
<col width="31%" />
|
||
<col width="35%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Objet</th>
|
||
<th class="head">Permissions</th>
|
||
<th class="head">Principals</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td rowspan="2"><tt class="docutils literal">bucket:poll</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;admin</span> id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">collection:create</tt></td>
|
||
<td><tt class="docutils literal">Authenticated</tt></td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal"><span class="pre">collection:&lt;poll</span> id&gt;</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;poll</span> author id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">record:create</tt></td>
|
||
<td><tt class="docutils literal">Everyone</tt></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Cartes&nbsp;colaboratives</strong></p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="34%" />
|
||
<col width="31%" />
|
||
<col width="35%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Objet</th>
|
||
<th class="head">Permissions</th>
|
||
<th class="head">Principals</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td rowspan="2"><tt class="docutils literal">bucket:maps</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;admin</span> id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">collection:create</tt></td>
|
||
<td><tt class="docutils literal">Authenticated</tt></td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal"><span class="pre">collection:&lt;map</span> id&gt;</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;map</span> author id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">read</tt></td>
|
||
<td><tt class="docutils literal">Everyone</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal"><span class="pre">record:&lt;record</span> id&gt;</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;maintainer</span> id&gt;</tt>
|
||
(<em>ex. event staff member
|
||
maintaining venues</em>)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p><strong>Plateformes</strong></p>
|
||
<p>Bien sûr, il y a plusieurs façons de modéliser les cas d&#8217;utilisation typiques.
|
||
Par exemple, on peut imaginer une plateforme de wikis (à la wikia.com), où les
|
||
wikis sont privés par défaut et certaines pages peuvent être rendues publiques&nbsp;:</p>
|
||
<table border="1" class="docutils">
|
||
<colgroup>
|
||
<col width="32%" />
|
||
<col width="30%" />
|
||
<col width="38%" />
|
||
</colgroup>
|
||
<thead valign="bottom">
|
||
<tr><th class="head">Objet</th>
|
||
<th class="head">Permissions</th>
|
||
<th class="head">Principals</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody valign="top">
|
||
<tr><td rowspan="3"><tt class="docutils literal">bucket:freewiki</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;administrator</span> id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">collection:create</tt></td>
|
||
<td><tt class="docutils literal">Authenticated</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">group:create</tt></td>
|
||
<td><tt class="docutils literal">Authenticated</tt></td>
|
||
</tr>
|
||
<tr><td rowspan="2"><tt class="docutils literal"><span class="pre">collection:&lt;wiki</span> id&gt;</tt></td>
|
||
<td><tt class="docutils literal">write</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">fxa:&lt;wiki</span> owner id&gt;</tt>,
|
||
<tt class="docutils literal"><span class="pre">group:&lt;editors</span> id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal">read</tt></td>
|
||
<td><tt class="docutils literal"><span class="pre">group:&lt;readers</span> id&gt;</tt></td>
|
||
</tr>
|
||
<tr><td><tt class="docutils literal"><span class="pre">record:&lt;page</span> id&gt;</tt></td>
|
||
<td><tt class="docutils literal">read</tt></td>
|
||
<td><tt class="docutils literal">Everyone</tt></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="section" id="l-api-http">
|
||
<h3>L&#8217;<span class="caps">API</span> <span class="caps">HTTP</span></h3>
|
||
<p>Lors de la création d&#8217;un objet, l&#8217;utilisateur se voit
|
||
attribué la permission <tt class="docutils literal">write</tt> sur l&#8217;objet&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><span class="nf">PUT</span> <span class="nn">/v1/buckets/servicedenuages_blog</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
|
||
<span class="na">Authorization</span><span class="o">:</span> <span class="l">Bearer 0b9c2625dc21ef05f6ad4ddf47c5f203837aa32ca42fced54c2625dc21efac32</span>
|
||
<span class="na">Accept</span><span class="o">:</span> <span class="l">application/json</span>
|
||
|
||
HTTP/1.1 201 Created
|
||
Content-Type: application/json; charset=utf-8
|
||
|
||
{
|
||
&quot;id&quot;: &quot;servicedenuages_blog&quot;,
|
||
&quot;permissions&quot;: {
|
||
&quot;write&quot;: [&quot;fxa:49d02d55ad10973b7b9d0dc9eba7fdf0&quot;]
|
||
}
|
||
}
|
||
</pre></div>
|
||
<p>Il est possible d&#8217;ajouter des permissions à l&#8217;aide de <tt class="docutils literal"><span class="caps">PATCH</span></tt> :</p>
|
||
<div class="highlight"><pre><span></span><span class="nf">PATCH</span> <span class="nn">/v1/buckets/servicedenuages_blog/collections/articles</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
|
||
<span class="na">Authorization</span><span class="o">:</span> <span class="l">Bearer 0b9c2625dc21ef05f6ad4ddf47c5f203837aa32ca42fced54c2625dc21efac32</span>
|
||
<span class="na">Accept</span><span class="o">:</span> <span class="l">application/json</span>
|
||
|
||
{
|
||
&quot;permissions&quot;: {
|
||
&quot;read&quot;: [&quot;+system.Everyone&quot;]
|
||
}
|
||
}
|
||
|
||
HTTP/1.1 201 Created
|
||
Content-Type: application/json; charset=utf-8
|
||
|
||
{
|
||
&quot;id&quot;: &quot;servicedenuages_blog&quot;,
|
||
&quot;permissions&quot;: {
|
||
&quot;write&quot;: [&quot;fxa:49d02d55ad10973b7b9d0dc9eba7fdf0&quot;],
|
||
&quot;read&quot;: [&quot;system.Everyone&quot;]
|
||
}
|
||
}
|
||
</pre></div>
|
||
<p>Pour le <tt class="docutils literal"><span class="caps">PATCH</span></tt> nous utilisons la syntaxe préfixée par un <tt class="docutils literal">+</tt> ou
|
||
par un <tt class="docutils literal">-</tt> pour ajouter ou enlever des <em>principals</em> sur un <span class="caps">ACL</span>.</p>
|
||
<p>Il est également possible de faire un <tt class="docutils literal"><span class="caps">PUT</span></tt> pour réinitialiser les ACLs,
|
||
sachant que le <tt class="docutils literal"><span class="caps">PUT</span></tt> va ajouter l&#8217;utilisateur courant à la
|
||
liste automatiquement mais qu&#8217;il pourra se retirer avec un <tt class="docutils literal"><span class="caps">PATCH</span></tt>.
|
||
Ajouter l&#8217;utilisateur courant permet d&#8217;éviter les situations où plus
|
||
personne n&#8217;a accès aux&nbsp;données.</p>
|
||
<div class="admonition note">
|
||
<p class="first admonition-title">Note</p>
|
||
<p class="last">La permission <tt class="docutils literal">create</tt> est valable pour <tt class="docutils literal"><span class="caps">POST</span></tt> mais aussi pour <tt class="docutils literal"><span class="caps">PUT</span></tt>
|
||
lorsque l&#8217;enregistrement n&#8217;existe&nbsp;pas.</p>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="le-cas-specifique-des-donnees-utilisateurs">
|
||
<h3>Le cas spécifique des données&nbsp;utilisateurs</h3>
|
||
<p>Une des fonctionnalités actuelles de <em>Kinto</em> est de pouvoir gérer des
|
||
collections d&#8217;enregistrements par&nbsp;utilisateur.</p>
|
||
<p>Sous <em>*nix</em> il est possible, pour une
|
||
application, de sauvegarder la configuration de l&#8217;utilisateur courant
|
||
dans son dossier personnel sans se soucier de l&#8217;emplacement sur
|
||
le disque en utilisant <tt class="docutils literal">~/</tt>.</p>
|
||
<p>Dans notre cas si une application souhaite sauvegarder les contacts d&#8217;un
|
||
utilisateur, elle peut utiliser le raccourci <tt class="docutils literal">~</tt> pour faire référence au
|
||
<em>bucket</em> <strong>personnel</strong> de l&#8217;utilisateur : <tt class="docutils literal"><span class="pre">/buckets/~/collections/contacts</span></tt></p>
|
||
<p>Cette <span class="caps">URL</span> retournera le code <tt class="docutils literal"><span class="caps">HTTP</span> 307</tt> vers le <em>bucket</em> de l&#8217;utilisateur courant&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><span class="nf">POST</span> <span class="nn">/v1/buckets/~/collections/contacts/records</span> <span class="kr">HTTP</span><span class="o">/</span><span class="m">1.1</span>
|
||
|
||
{
|
||
&quot;name&quot;: &quot;Rémy&quot;,
|
||
&quot;emails&quot;: [&quot;remy@example.com&quot;],
|
||
&quot;phones&quot;: [&quot;+330820800800&quot;]
|
||
}
|
||
|
||
HTTP/1.1 307 Temporary Redirect
|
||
Location: /v1/buckets/fxa:49d02d55ad10973b7b9d0dc9eba7fdf0/collections/contacts/records
|
||
</pre></div>
|
||
<p>Ainsi il est tout à fait possible à Alice de partager ses contacts
|
||
avec Bob. Il lui suffit pour cela de donner la permission <tt class="docutils literal">read</tt> à
|
||
Bob sur sa collection et de donner l&#8217;<span class="caps">URL</span> complète
|
||
<tt class="docutils literal">/v1/buckets/fxa:49d02d55ad10973b7b9d0dc9eba7fdf0/collections/contacts/records</tt>
|
||
à&nbsp;Bob.</p>
|
||
</div>
|
||
<div class="section" id="la-delegation-des-permissions">
|
||
<h3>La délégation des&nbsp;permissions</h3>
|
||
<p>Dans le cas de <em>Kinto</em>, nous avons défini un format pour restreindre les
|
||
permissions via les scopes OAuth2:
|
||
<tt class="docutils literal"><span class="pre">storage:&lt;bucket_id&gt;:&lt;collection_id&gt;:&lt;permissions_list&gt;</span></tt>.</p>
|
||
<p>Ainsi, si on reprend l&#8217;exemple précédent de la liste de tâches, il est possible pour
|
||
Bob de créer un token OAuth spécifique avec les <em>scopes</em> suivants :
|
||
<tt class="docutils literal">profile storage:todolist:tasks:write <span class="pre">storage:~:contacts:read+records:create</span></tt></p>
|
||
<p>Donc, bien que Bob a la permission <tt class="docutils literal">write</tt> sur ses contacts,
|
||
l&#8217;application utilisant ce token pourra uniquement lire les contacts
|
||
existants et en ajouter de&nbsp;nouveaux.</p>
|
||
<p>Une partie de la complexité est donc de réussir à présenter ces <em>scopes</em> de
|
||
manière lisible à l&#8217;utilisateur, afin qu&#8217;il choisisse quelles permissions
|
||
donner aux applications qui agissent en son&nbsp;nom.</p>
|
||
<p>Voilà où nous en sommes de notre réflexion&nbsp;!</p>
|
||
<p>Si vous avez des choses à ajouter, des points de désaccord ou autres
|
||
réflexions, n&#8217;hésitez pas à nous interrompre pendant qu&#8217;il est encore temps&nbsp;!</p>
|
||
</div>
|
||
</div>
|
||
</content><category term="code"></category></entry><entry><title>Eco-système et stockage générique</title><link href="https://blog.notmyidea.org/eco-systeme-et-stockage-generique.html" rel="alternate"></link><published>2015-04-30T00:00:00+02:00</published><updated>2015-04-30T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-04-30:/eco-systeme-et-stockage-generique.html</id><summary type="html">
|
||
<p><strong>tl;dr Nous devons construire un service de suivi de paiements, et nous
|
||
hésitons à continuer à nous entêter avec notre propre solution de&nbsp;stockage/synchronisation.</strong></p>
|
||
<p>Comme nous l&#8217;écrivions <a href="https://blog.notmyidea.org/service-de-nuages-fr.html">dans l&#8217;article
|
||
précédent</a>, nous
|
||
souhaitons construire une solution de stockage générique. On refait
|
||
<a href="http://daybed.readthedocs.org">Daybed</a> chez Mozilla&nbsp;!</p>
|
||
<p>Notre objectif est …</p></summary><content type="html">
|
||
<p><strong>tl;dr Nous devons construire un service de suivi de paiements, et nous
|
||
hésitons à continuer à nous entêter avec notre propre solution de&nbsp;stockage/synchronisation.</strong></p>
|
||
<p>Comme nous l&#8217;écrivions <a href="https://blog.notmyidea.org/service-de-nuages-fr.html">dans l&#8217;article
|
||
précédent</a>, nous
|
||
souhaitons construire une solution de stockage générique. On refait
|
||
<a href="http://daybed.readthedocs.org">Daybed</a> chez Mozilla&nbsp;!</p>
|
||
<p>Notre objectif est simple: permettre aux développeurs d&#8217;application,
|
||
internes à Mozilla ou du monde entier, de faire persister et
|
||
synchroniser facilement des données associées à un&nbsp;utilisateur.</p>
|
||
<div id="storage-specs">
|
||
|
||
Les aspects de l&#8217;architecture qui nous semblent incontournables:
|
||
|
||
</div>
|
||
|
||
<ul>
|
||
<li>La solution doit reposer sur un protocole, et non sur une
|
||
implémentation&nbsp;;</li>
|
||
<li>L&#8217;auto-hébergement de l&#8217;ensemble doit être simplissime&nbsp;;</li>
|
||
<li>L&#8217;authentification doit être <em>pluggable</em>, voire décentralisée
|
||
(OAuth2, FxA, Persona)&nbsp;;</li>
|
||
<li>Les enregistrements doivent pouvoir être validés par le serveur&nbsp;;</li>
|
||
<li>Les données doivent pouvoir être stockées dans n&#8217;importe quel
|
||
backend&nbsp;;</li>
|
||
<li>Un système de permissions doit permettre de protéger des
|
||
collections, ou de partager des enregistrements de manière fine&nbsp;;</li>
|
||
<li>La résolution de conflits doit pouvoir avoir lieu sur le serveur&nbsp;;</li>
|
||
<li>Le client doit être pensé «*offline-first*»&nbsp;;</li>
|
||
<li>Le client doit pouvoir réconcilier les données simplement&nbsp;;</li>
|
||
<li>Le client doit pouvoir être utilisé aussi bien dans le navigateur
|
||
que côté serveur&nbsp;;</li>
|
||
<li>Tous les composants se doivent d´être simples et substituables&nbsp;facilement.</li>
|
||
</ul>
|
||
<p>La première question qui nous a été posée fût «*Pourquoi vous
|
||
n&#8217;utilisez pas PouchDB ou Remote Storage&nbsp;?*»</p>
|
||
<h2 id="remote-storage">Remote&nbsp;Storage</h2>
|
||
<p>Remote Storage est un standard ouvert pour du stockage par utilisateur.
|
||
<a href="http://tools.ietf.org/html/draft-dejong-remotestorage-04">La
|
||
specification</a>
|
||
se base sur des standards déjà existants et éprouvés: Webfinger, OAuth
|
||
2, <span class="caps">CORS</span> et <span class="caps">REST</span>.</p>
|
||
<p>L&#8217;<span class="caps">API</span> est simple, des <a href="http://blog.cozycloud.cc/news/2014/08/12/when-unhosted-meets-cozy-cloud/">projets prestigieux
|
||
l&#8217;utilisent</a>.
|
||
Il y a plusieurs <a href="https://github.com/jcoglan/restore">implémentations</a>
|
||
du serveur, et il existe <a href="https://www.npmjs.com/package/remotestorage-server">un squelette
|
||
Node</a> pour
|
||
construire un serveur sur&nbsp;mesure.</p>
|
||
<p><img alt="Remote Storage widget" src="%7Bfilename%7D/images/remotestorage-widget.png"></p>
|
||
<p>Le client
|
||
<a href="https://github.com/remotestorage/remotestorage.js/">remoteStorage.js</a>
|
||
permet d&#8217;intégrer la solution dans les applications Web. Il se charge du
|
||
«store local», du cache, de la synchronization, et fournit un widget qui
|
||
permet aux utilisateurs des applications de choisir le serveur qui
|
||
recevra les données (via&nbsp;Webfinger).</p>
|
||
<p><a href="https://github.com/michielbdejong/ludbud">ludbud</a>, la version épurée de
|
||
<em>remoteStorage.js</em>, se limite à l&#8217;abstraction du stockage distant. Cela
|
||
permettrait à terme, d&#8217;avoir une seule bibliothèque pour stocker dans un
|
||
serveur <em>remoteStorage</em>, <em>ownCloud</em> ou chez les méchants comme <em>Google
|
||
Drive</em> ou <em>Dropbox</em>.</p>
|
||
<p>Au premier abord, la spécification correspond à ce que nous voulons&nbsp;accomplir:</p>
|
||
<ul>
|
||
<li>La philosophie du protocole est&nbsp;saine;</li>
|
||
<li>L&#8217;éco-système est bien&nbsp;fichu;</li>
|
||
<li>La vision politique colle: redonner le contrôle des données aux
|
||
utilisateurs (voir <a href="http://unhosted.org/">unhosted</a>);</li>
|
||
<li>Les choix techniques compatibles avec ce qu&#8217;on a commencé (<span class="caps">CORS</span>,
|
||
<span class="caps">REST</span>, OAuth&nbsp;2);</li>
|
||
</ul>
|
||
<p>En revanche, vis à vis de la manipulation des données, il y a plusieurs
|
||
différences avec ce que nous souhaitons&nbsp;faire:</p>
|
||
<ul>
|
||
<li>L&#8217;<span class="caps">API</span> suit globalement une métaphore «fichiers» (dossier/documents),
|
||
plutôt que «données» (collection/enregistrements)&nbsp;;</li>
|
||
<li>Il n&#8217;y a pas de validation des enregistrements selon un schéma (même
|
||
si <a href="https://remotestorage.io/doc/code/files/baseclient/types-js.html">certaines
|
||
implémentations</a>
|
||
du protocole le font)&nbsp;;</li>
|
||
<li>Il n&#8217;y a pas la possibilité de trier/filtrer les enregistrements
|
||
selon des attributs&nbsp;;</li>
|
||
<li>Les permissions <a href="https://groups.google.com/forum/#!topic/unhosted/5_NOGq8BPTo">se limitent à
|
||
privé/public</a>
|
||
(et <a href="https://github.com/remotestorage/spec/issues/58#issue-27249452">l&#8217;auteur envisage plutôt un modèle à la
|
||
Git</a>)[1]&nbsp;;</li>
|
||
</ul>
|
||
<p>En résumé, il semblerait que ce que nous souhaitons faire avec le
|
||
stockage d&#8217;enregistrements validés est complémentaire avec <em>Remote
|
||
Storage</em>.</p>
|
||
<p>Si des besoins de persistence orientés «fichiers» se présentent, a
|
||
priori nous aurions tort de réinventer les solutions apportées par cette
|
||
spécification. Il y a donc de grandes chances que nous l´intégrions à
|
||
terme, et que <em>Remote Storage</em> devienne une facette de notre&nbsp;solution.</p>
|
||
<h2 id="pouchdb">PouchDB</h2>
|
||
<p><a href="http://pouchdb.com/">PouchDB</a> est une bibliothèque JavaScript qui
|
||
permet de manipuler des enregistrements en local et de les synchroniser
|
||
vers une base&nbsp;distante.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">javascript</span>
|
||
<span class="k">var</span><span class="w"> </span><span class="n">db</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">new</span><span class="w"> </span><span class="n">PouchDB</span><span class="p">(</span><span class="s1">&#39;dbname&#39;</span><span class="p">);</span>
|
||
|
||
<span class="n">db</span><span class="o">.</span><span class="n">put</span><span class="p">({</span>
|
||
<span class="w"> </span><span class="n">_id</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;dave@gmail.com&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">name</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;David&#39;</span><span class="p">,</span>
|
||
<span class="w"> </span><span class="n">age</span><span class="p">:</span><span class="w"> </span><span class="mi">68</span>
|
||
<span class="p">});</span>
|
||
|
||
<span class="n">db</span><span class="o">.</span><span class="n">replicate</span><span class="o">.</span><span class="n">to</span><span class="p">(</span><span class="s1">&#39;http://example.com/mydb&#39;</span><span class="p">);</span>
|
||
</code></pre></div>
|
||
|
||
<p>Le projet a le vent en poupe, bénéficie de nombreux contributeurs,
|
||
l&#8217;éco-système est très riche et l&#8217;adoption par des projets <a href="https://github.com/hoodiehq/wip-hoodie-store-on-pouchdb">comme
|
||
Hoodie</a> ne fait
|
||
que confirmer la pertinence de l&#8217;outil pour les développeurs&nbsp;frontend.</p>
|
||
<p><em>PouchDB</em> gère un « store » local, dont la persistence est abstraite et
|
||
<a href="http://pouchdb.com/2014/07/25/pouchdb-levels-up.html">repose sur</a> l&#8217;<span class="caps">API</span>
|
||
<a href="https://github.com/level/levelup#relationship-to-leveldown">LevelDown</a>
|
||
pour persister les données dans <a href="https://github.com/Level/levelup/wiki/Modules#storage-back-ends">n&#8217;importe quel
|
||
backend</a>.</p>
|
||
<p>Même si <em>PouchDB</em> adresse principalement les besoins des applications
|
||
«*offline-first*», il peut être utilisé aussi bien dans le navigateur
|
||
que côté serveur, via&nbsp;Node.</p>
|
||
<h3 id="synchronisation">Synchronisation</h3>
|
||
<p>La synchronisation (ou réplication) des données locales s&#8217;effectue sur
|
||
un <a href="http://couchdb.apache.org/">CouchDB</a>&nbsp;distant.</p>
|
||
<p>Le projet <a href="https://github.com/pouchdb/pouchdb-server">PouchDB Server</a>
|
||
implémente l&#8217;<span class="caps">API</span> de CouchDB en NodeJS. Comme <em>PouchDB</em> est utilisé, on
|
||
obtient un service qui se comporte comme un <em>CouchDB</em> mais qui stocke
|
||
ses données n&#8217;importe où, dans un <em>Redis</em> ou un <em>PostgreSQL</em> par&nbsp;exemple.</p>
|
||
<p>La synchronisation est complète. Autrement dit, tous les enregistrements
|
||
qui sont sur le serveur se retrouvent synchronisés dans le client. Il
|
||
est possible de filtrer les collections synchronisées, mais cela <a href="http://pouchdb.com/2015/04/05/filtered-replication.html">n&#8217;a
|
||
pas pour objectif de sécuriser l&#8217;accès aux
|
||
données</a>.</p>
|
||
<p>L&#8217;approche recommandée pour cloisonner les données par utilisateur
|
||
consiste à créer <a href="https://github.com/nolanlawson/pouchdb-authentication#some-people-can-read-some-docs-some-people-can-write-those-same-docs">une base de données par
|
||
utilisateur</a>.</p>
|
||
<p>Ce n&#8217;est pas forcément un problème, CouchDB <a href="https://mail-archives.apache.org/mod_mbox/couchdb-user/201401.mbox/%3C52CEB873.7080404@ironicdesign.com%3E">supporte des centaines de
|
||
milliers de bases sans
|
||
sourciller</a>.
|
||
Mais selon les cas d&#8217;utilisation, le cloisement n&#8217;est pas toujours
|
||
facile à déterminer (par rôle, par application, par collection,&nbsp;&#8230;).</p>
|
||
<h2 id="le-cas-dutilisation-payments">Le cas d&#8217;utilisation « Payments&nbsp;»</h2>
|
||
<p><img alt="Put Payments Here -- Before the Internet - CC-NC-SA Katy Silberger
|
||
https://www.flickr.com/photos/katysilbs/11163812186" src="%7Bfilename%7D/images/put-payments.jpg"></p>
|
||
<p>Dans les prochaines semaines, nous devrons mettre sur pied un prototype
|
||
pour tracer l&#8217;historique des paiements et abonnements d&#8217;un&nbsp;utilisateur.</p>
|
||
<p>Le besoin est&nbsp;simple:</p>
|
||
<ul>
|
||
<li>l&#8217;application « Payment » enregistre les paiements et abonnements
|
||
d&#8217;un utilisateur pour une application&nbsp;donnée;</li>
|
||
<li>l&#8217;application « Donnée » interroge le service pour vérifier qu&#8217;un
|
||
utilisateur a payé ou est&nbsp;abonné;</li>
|
||
<li>l&#8217;utilisateur interroge le service pour obtenir la liste de tous ses&nbsp;abonnements.</li>
|
||
</ul>
|
||
<p>Seule l&#8217;application « Payment » a le droit de créer/modifier/supprimer
|
||
des enregistrements, les deux autres ne peuvent que consulter en lecture&nbsp;seule.</p>
|
||
<p>Une application donnée ne peut pas accéder aux paiements des autres
|
||
applications, et un utilisateur ne peut pas accéder aux paiements des
|
||
autres&nbsp;utilisateurs.</p>
|
||
<h3 id="avec-remotestorage">Avec&nbsp;RemoteStorage</h3>
|
||
<p><img alt="Remote Love - CC-BY-NC Julie
|
||
https://www.flickr.com/photos/mamajulie2008/2609549461" src="%7Bfilename%7D/images/remote-love.jpg"></p>
|
||
<p>Clairement, l&#8217;idée de <em>RemoteStorage</em> est de dissocier l&#8217;application
|
||
executée, et les données créées par l&#8217;utilisateur avec&nbsp;celle-ci.</p>
|
||
<p>Dans notre cas, c&#8217;est l&#8217;application « Payment » qui manipule des données
|
||
concernant un utilisateur. Mais celles-ci ne lui appartiennent pas
|
||
directement: certes un utilisateur doit pouvoir les supprimer, surtout
|
||
pas en créer ou les&nbsp;modifier!</p>
|
||
<p>La notion de permissions limitée à privé/publique ne suffit pas dans ce
|
||
cas&nbsp;précis.</p>
|
||
<h3 id="avec-pouchdb">Avec&nbsp;PouchDB</h3>
|
||
<p>Il va falloir créer une <em>base de données</em> par utilisateur, afin d&#8217;isoler
|
||
les enregistrements de façon sécurisée. Seule l&#8217;application « Payment »
|
||
aura tous les droits sur les&nbsp;databases.</p>
|
||
<p>Mais cela ne suffit&nbsp;pas.</p>
|
||
<p>Il ne faut pas qu&#8217;une application puisse voir les paiements des autres
|
||
applications, donc il va aussi falloir recloisonner, et créer une <em>base
|
||
de données</em> par&nbsp;application.</p>
|
||
<p>Quand un utilisateur voudra accéder à l&#8217;ensemble de ses paiements, il
|
||
faudra agréger les <em>databases</em> de toutes les applications. Quand
|
||
l&#8217;équipe marketing voudra faire des statistiques sur l&#8217;ensemble des
|
||
applications, il faudra agrégér des centaines de milliers de
|
||
<em>databases</em>.</p>
|
||
<p>Ce qui est fort dommage, puisqu&#8217;il est probable que les paiements ou
|
||
abonnements d&#8217;un utilisateur pour une application se comptent sur les
|
||
doigts d&#8217;une main. Des centaines de milliers de bases contenant moins de
|
||
5 enregistrements&nbsp;?</p>
|
||
<p>De plus, dans le cas de l&#8217;application « Payment », le serveur est
|
||
implémenté en Python. Utiliser un wrapper JavaScript comme le fait
|
||
<a href="https://pythonhosted.org/Python-PouchDB/">python-pouchdb</a> cela ne nous
|
||
fait pas trop&nbsp;rêver.</p>
|
||
<h2 id="un-nouvel-eco-systeme">Un nouvel éco-système&nbsp;?</h2>
|
||
<p><img alt="Wagon wheel - CC-BY-NC-SA arbyreed
|
||
https://www.flickr.com/photos/19779889@N00/16161808220" src="%7Bfilename%7D/images/wagon-wheel.jpg"></p>
|
||
<p>Évidemment, quand on voit la richesse des projets <em>PouchDB</em> et <em>Remote
|
||
Storage</em> et la dynamique de ces communautés, il est légitime d&#8217;hésiter
|
||
avant de développer une solution&nbsp;alternative.</p>
|
||
<p>Quand nous avons créé le serveur <em>Reading List</em>, nous l&#8217;avons construit
|
||
avec <a href="http://cliquet.readthedocs.org/">Cliquet</a>, ce fût l&#8217;occasion de
|
||
mettre au point <a href="http://cliquet.readthedocs.org/en/latest/api/">un protocole très
|
||
simple</a>, fortement
|
||
inspiré de <a href="http://en.wikipedia.org/wiki/Firefox_Sync">Firefox Sync</a>,
|
||
pour faire de la synchronisation&nbsp;d&#8217;enregistrements.</p>
|
||
<p>Et si les clients <em>Reading List</em> ont pu être implémentés en quelques
|
||
semaines, que ce soit en JavaScript, Java (Android) et <span class="caps">ASM</span> (Add-on
|
||
Firefox), c&#8217;est que le principe «*offline first*» du service est&nbsp;trivial.</p>
|
||
<h3 id="les-compromis">Les&nbsp;compromis</h3>
|
||
<p>Évidemment, nous n&#8217;avons pas la prétention de concurrencer <em>CouchDB</em>.
|
||
Nous faisons plusieurs&nbsp;concessions:</p>
|
||
<ul>
|
||
<li>De base, les collections d&#8217;enregistrements sont cloisonnées par&nbsp;utilisateur;</li>
|
||
<li>Pas d&#8217;historique des&nbsp;révisions;</li>
|
||
<li>Pas de diff sur les enregistrements entre&nbsp;révisions;</li>
|
||
<li>De base, pas de résolution de conflit&nbsp;automatique;</li>
|
||
<li>Pas de synchronisation par flux (<em>streams</em>);</li>
|
||
</ul>
|
||
<p>Jusqu&#8217;à preuve du contraire, ces compromis excluent la possibilité
|
||
d&#8217;implémenter un <a href="https://github.com/pouchdb/pouchdb/blob/master/lib/adapters/http/http.js#L721-L946">adapter
|
||
PouchDB</a>
|
||
pour la synchronisation avec le protocole <span class="caps">HTTP</span> de <em>Cliquet</em>.</p>
|
||
<p>Dommage puisque capitaliser sur l&#8217;expérience client de <em>PouchDB</em> au
|
||
niveau synchro client semble être une très bonne&nbsp;idée.</p>
|
||
<p>En revanche, nous avons plusieurs fonctionnalités&nbsp;intéressantes:</p>
|
||
<ul>
|
||
<li>Pas de&nbsp;map-reduce;</li>
|
||
<li>Synchronisation partielle et/ou ordonnée et/ou paginée&nbsp;;</li>
|
||
<li>Le client choisit, via des headers, d&#8217;écraser la donnée ou de
|
||
respecter la version du serveur&nbsp;;</li>
|
||
<li>Un seul serveur à déployer pour N applications&nbsp;;</li>
|
||
<li>Auto-hébergement simplissime&nbsp;;</li>
|
||
<li>Le client peut choisir de ne pas utiliser de « store local » du tout&nbsp;;</li>
|
||
<li>Dans le client <span class="caps">JS</span>, la gestion du « store local » sera externalisée
|
||
(on pense à <a href="https://github.com/mozilla/localForage">LocalForage</a> ou
|
||
<a href="https://github.com/dfahlander/Dexie.js">Dexie.js</a>)&nbsp;;</li>
|
||
</ul>
|
||
<p>Et, on répond au reste des <a href="#storage-specs">specifications mentionnées au début de
|
||
l&#8217;article</a>&nbsp;!</p>
|
||
<h3 id="les-arguments-philosophiques">Les arguments&nbsp;philosophiques</h3>
|
||
<p>Il est <a href="http://en.wikipedia.org/wiki/Law_of_the_instrument">illusoire de penser qu&#8217;on peut tout faire avec un seul
|
||
outil</a>.</p>
|
||
<p>Nous avons d&#8217;autres cas d&#8217;utilisations dans les cartons qui semblent
|
||
correspondre au scope de <em>PouchDB</em> (<em>pas de notion de permissions ou de
|
||
partage, environnement JavaScript, &#8230;</em>). Nous saurons en tirer profit
|
||
quand cela s&#8217;avèrera pertinent&nbsp;!</p>
|
||
<p>L&#8217;éco-système que nous voulons construire tentera de couvrir les cas
|
||
d&#8217;utilisation qui sont mal adressés par <em>PouchDB</em>. Il se&nbsp;voudra:</p>
|
||
<ul>
|
||
<li>Basé sur notre protocole très simple&nbsp;;</li>
|
||
<li>Minimaliste et multi-usages (<em>comme la fameuse <span class="caps">2CV</span></em>)&nbsp;;</li>
|
||
<li>Naïf (<em>pas de rocket science</em>)&nbsp;;</li>
|
||
<li>Sans magie (<em>explicite et facile à réimplémenter from scratch</em>)&nbsp;;</li>
|
||
</ul>
|
||
<p><a href="http://cliquet.readthedocs.org/en/latest/rationale.html">La philosophie et les fonctionnalités du toolkit python
|
||
Cliquet</a> seront
|
||
bien entendu à l&#8217;honneur&nbsp;:)</p>
|
||
<p>Quant à <em>Remote Storage</em>, dès que le besoin se présentera, nous serons
|
||
très fier de rejoindre l&#8217;initiative, mais pour l&#8217;instant cela nous
|
||
paraît risqué de démarrer en tordant la&nbsp;solution.</p>
|
||
<h3 id="les-arguments-pratiques">Les arguments&nbsp;pratiques</h3>
|
||
<p>Avant d&#8217;accepter de déployer une solution à base de <em>CouchDB</em>, les <em>ops</em>
|
||
de Mozilla vont nous demander de leur prouver par A+B que ce n&#8217;est pas
|
||
faisable avec les stacks qui sont déjà rodées en interne (i.e. MySQL,
|
||
Redis,&nbsp;PostgreSQL).</p>
|
||
<p>De plus, on doit s&#8217;engager sur une pérennité d&#8217;au moins 5 ans pour les
|
||
données. Avec <em>Cliquet</em>, en utilisant le backend PostgreSQL, les données
|
||
sont persistées à plat dans un <a href="https://github.com/mozilla-services/cliquet/blob/40aa33/cliquet/storage/postgresql/schema.sql#L14-L28">schéma PostgreSQL tout
|
||
bête</a>.
|
||
Ce qui ne sera pas le cas d&#8217;un adapteur LevelDown qui va manipuler des
|
||
notions de révisions éclatées dans un schéma&nbsp;clé-valeur.</p>
|
||
<p>Si nous basons le service sur <em>Cliquet</em>, comme c&#8217;est le cas avec
|
||
<a href="http://kinto.readthedocs.org">Kinto</a>, tout le travail d&#8217;automatisation
|
||
de la mise en production (<em>monitoring, builds <span class="caps">RPM</span>, Puppet&#8230;</em>) que nous
|
||
avons fait pour <em>Reading List</em> est complètement&nbsp;réutilisable.</p>
|
||
<p>De même, si on repart avec une stack complètement différente, nous
|
||
allons devoir recommencer tout le travail de rodage, de profiling et
|
||
d&#8217;optimisation effectué au premier&nbsp;trimestre.</p>
|
||
<h2 id="les-prochaines-etapes">Les prochaines&nbsp;étapes</h2>
|
||
<p>Et il est encore temps de changer de stratégie :) Nous aimerions avoir
|
||
un maximum de retours ! C&#8217;est toujours une décision difficile à
|
||
prendre&#8230; <code>&lt;/appel à troll&gt;</code></p>
|
||
<ul>
|
||
<li>Tordre un éco-système existant vs. constuire sur mesure&nbsp;;</li>
|
||
<li>Maîtriser l&#8217;ensemble vs. s&#8217;intégrer&nbsp;;</li>
|
||
<li>Contribuer vs. refaire&nbsp;;</li>
|
||
<li>Guider vs.&nbsp;suivre.</li>
|
||
</ul>
|
||
<p>Nous avons vraiment l&#8217;intention de rejoindre l&#8217;initiative
|
||
<a href="https://nobackend.org/">no-backend</a>, et ce premier pas n&#8217;exclue pas que
|
||
nous convergions à terme ! Peut-être que nous allons finir par rendre
|
||
notre service compatible avec <em>Remote Storage</em>, et peut-être que
|
||
<em>PouchDB</em> deviendra plus agnostique quand au protocole de&nbsp;synchronisation&#8230;</p>
|
||
<p><img alt="XKCD — Standards
|
||
https://xkcd.com/927/" src="%7Bfilename%7D/images/standards.png"></p>
|
||
<p>Utiliser ce nouvel écosystème pour le projet « Payments » va nous
|
||
permettre de mettre au point un système de permissions (<em>probablement
|
||
basé sur les scopes OAuth</em>) qui correspond au besoin exprimé. Et nous
|
||
avons bien l&#8217;intention de puiser dans <a href="http://blog.daybed.io/daybed-revival.html">notre expérience avec Daybed sur
|
||
le sujet</a>.</p>
|
||
<p>Nous extrairons aussi le code des clients implémentés pour <em>Reading
|
||
List</em> afin de faire un client JavaScript&nbsp;minimaliste.</p>
|
||
<p>En partant dans notre coin, nous prenons plusieurs&nbsp;risques:</p>
|
||
<ul>
|
||
<li>réinventer une roue dont nous n&#8217;avons pas connaissance&nbsp;;</li>
|
||
<li>échouer à faire de l&#8217;éco-système <em>Cliquet</em> un projet communautaire&nbsp;;</li>
|
||
<li>échouer à positionner <em>Cliquet</em> dans la niche des cas non couverts
|
||
par PouchDB&nbsp;:)</li>
|
||
</ul>
|
||
<p>Comme <a href="http://pouchdb.com/2015/04/05/filtered-replication.html">le dit Giovanni
|
||
Ornaghi</a>:</p>
|
||
<blockquote>
|
||
<p>Rolling out your set of webservices, push notifications, or background
|
||
services might give you more control, but at the same time it will
|
||
force you to engineer, write, test, and maintain a whole new&nbsp;ecosystem.</p>
|
||
</blockquote>
|
||
<p>C&#8217;est justement l&#8217;éco-système dont est responsable l&#8217;équipe <em>Mozilla
|
||
Cloud Services</em>!</p>
|
||
<ol>
|
||
<li>Il existe le <a href="https://sharesome.5apps.com/">projet Sharesome</a> qui
|
||
permet de partager publiquement des ressources de son <em>remote
|
||
Storage</em>.</li>
|
||
</ol></content><category term="code"></category></entry><entry><title>Service de nuages !</title><link href="https://blog.notmyidea.org/service-de-nuages-fr.html" rel="alternate"></link><published>2015-04-01T00:00:00+02:00</published><updated>2015-04-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2015-04-01:/service-de-nuages-fr.html</id><summary type="html"><p class="first last">Retour sur le premier trimestre 2015: Readinglist, Kinto,&nbsp;Cliquet.</p>
|
||
</summary><content type="html"><p><em>Cet article est repris depuis le blog « Service de Nuages » de mon équipe à&nbsp;Mozilla</em></p>
|
||
<p>Pas mal de changements depuis le début de l&#8217;année pour l&#8217;équipe
|
||
«cloud-services»&nbsp;francophone!</p>
|
||
<p>Tout d&#8217;abord, nouvelle importante, l&#8217;équipe s&#8217;étoffe avec des profils assez
|
||
complémentaires: <a class="reference external" href="https://nicolas.perriault.net/">n1k0</a> et <a class="reference external" href="http://mathieu-leplatre.info">Mathieu</a> sont venus prêter main forte à <a class="reference external" href="http://ziade.org/">Tarek</a>, <a class="reference external" href="http://natim.ionyse.com">Rémy</a> et <a class="reference external" href="http://notmyidea.org">Alexis</a>.</p>
|
||
<p>Le début de l&#8217;année a vu le lancement de <a class="reference external" href="https://www.mozilla.org/en-US/firefox/hello/">Firefox Hello</a> ce qui nous a permis de passer
|
||
à l&#8217;échelle <a class="reference external" href="https://github.com/mozilla-services/loop-server">le serveur</a>,
|
||
écrit en Node.js®, pour&nbsp;l&#8217;occasion.</p>
|
||
<div class="section" id="un-serveur-de-listes-de-lecture">
|
||
<h2>Un serveur de listes de&nbsp;lecture</h2>
|
||
<p>En parallèle, un projet de <a class="reference external" href="https://readinglist.readthedocs.org">synchronisation de liste de lecture</a> (<em>Reading List</em>) a vu le jour. L&#8217;idée
|
||
étant de pouvoir marquer des pages &#8220;à lire pour plus tard&#8221; et de continuer la
|
||
lecture sur n&#8217;importe quel périphérique synchronisé (Firefox pour Android ou
|
||
Firefox Desktop). Un équivalent libre à <a class="reference external" href="http://getpocket.com">Pocket</a> en quelque sorte, qu&#8217;il est
|
||
possible d&#8217;héberger&nbsp;soit-même.</p>
|
||
<img alt="Capture d'écran de Firefox nightly avec readinglist." src="https://blog.notmyidea.org/images/readinglist-screenshot.png" />
|
||
<p>Pour le construire, nous aurions pu réutiliser <a class="reference external" href="https://github.com/mozilla-services/server-syncstorage">Firefox Sync</a>, après tout
|
||
c&#8217;est un service de synchronisation de données très robuste, construit avec <a class="reference external" href="http://cornice.readthedocs.org/">Cornice</a>.
|
||
Mais seulement, <em>Sync</em> n&#8217;a pas été pensé pour garantir la pérennité des données,
|
||
et la marche était trop haute pour changer ça en&nbsp;profondeur.</p>
|
||
<p>Nous aurions pu aussi nous contenter de faire une énième application qui expose
|
||
une <span class="caps">API</span> et persiste des données dans une base de&nbsp;données.</p>
|
||
<p>Mais cette nouvelle petite équipe n&#8217;est pas là par hasard&nbsp;:)</p>
|
||
</div>
|
||
<div class="section" id="la-daybed-team">
|
||
<h2>La «Daybed&nbsp;Team»</h2>
|
||
<p>On partage une vision: un service générique de stockage de données ! Peut-être
|
||
que ça vous rappelle <a class="reference external" href="https://daybed.io">un certain projet nommé Daybed</a> ?
|
||
Pour les applications clientes, JavaScript, mobiles ou autres, l&#8217;utilisation de
|
||
ce service doit être un jeu d&#8217;enfant ! L&#8217;application gère ses données
|
||
localement (aka offline-first), et synchronise à la&nbsp;demande.</p>
|
||
<p>Ici, le cœur du serveur <em>Reading List</em> est justement une <span class="caps">API</span> &#8220;<span class="caps">CRUD</span>&#8221; (Create,
|
||
Retrieve, Update, Delete), qui gère de la synchronisation et de
|
||
l&#8217;authentification. Nous avons donc pris le parti de faire une <span class="caps">API</span> &#8220;simple&#8221;,
|
||
avec le moins de spécificités possible, qui poserait les bases d&#8217;un service
|
||
générique. Notamment parce qu&#8217;il y a d&#8217;autres projets dans la même trempe qui vont&nbsp;suivre.</p>
|
||
<p>Pas mal d&#8217;expérience ayant été accumulée au sein de l&#8217;équipe, avec d&#8217;une part la
|
||
création de <em>Firefox Sync</em>, et d&#8217;autre part avec <em>Daybed</em>, notre side-project, nous
|
||
tentons de ne pas reproduire les mêmes erreurs, tout en gardant les concepts
|
||
qui ont fait leurs&nbsp;preuves.</p>
|
||
<p>Par exemple, nous avons conservé le mécanisme de collections d&#8217;enregistrements
|
||
et de <em>timestamp</em> de <em>Sync</em>. Comme ces problématiques sont récurrentes, voire
|
||
incontournables, nous avons décidé de reprendre le protocole de synchronisation,
|
||
de l&#8217;étendre légèrement et surtout de le dissocier du projet de listes de&nbsp;lecture.</p>
|
||
</div>
|
||
<div class="section" id="le-mecanisme-qui-force-a-aller-de-l-avant">
|
||
<h2>Le mécanisme qui force à aller de&nbsp;l&#8217;avant</h2>
|
||
<p>Comme première pierre à l&#8217;édifice, nous avons donné naissance au projet
|
||
<a class="reference external" href="https://cliquet.readthedocs.org">Cliquet</a>, dont l&#8217;idée principale est de
|
||
fournir une implémentation de ce protocole en python, tout en factorisant
|
||
l&#8217;ensemble de nos bonnes pratiques (pour la prod&nbsp;notamment).</p>
|
||
<img alt="Logo du projet Cliquet" class="align-right" src="https://blog.notmyidea.org/images/cliquet/cliquet-logo.png" />
|
||
<p>L&#8217;avantage d&#8217;avoir un protocole plutôt qu&#8217;un monolithe, c&#8217;est que si vous
|
||
préférez Asyncio, io.js ou Go, on vous encouragera à publier votre
|
||
implémentation alternative&nbsp;!</p>
|
||
<p>Avec <em>Cliquet</em>, le code du serveur liste de lecture consiste principalement
|
||
à définir un schéma pour les enregistrements, puis à forcer des valeurs de
|
||
champs sur certains appels. Cela réduit ce projet à quelques dizaines de lignes
|
||
de&nbsp;code.</p>
|
||
<p>Quant au futur service de stockage générique, <a class="reference external" href="http://kinto.readthedocs.org">le projet</a> en est encore à ses balbutiements mais c&#8217;est
|
||
bel et bien en route ! Il permet déjà d&#8217;être branché comme backend de stockage
|
||
dans une application <em>Cliquet</em>, et ça <a class="reference external" href="https://github.com/mozilla-services/kinto/blob/0.2.1/kinto/views/collection.py">implémenté en 20 lignes de code</a>!</p>
|
||
<p>Ah, et cette fois, nous ne construirons les fonctionnalités qu&#8217;à partir des
|
||
besoins concrets qui surviennent. Ça paraît tout bête, mais sur <em>Daybed</em> on
|
||
l&#8217;a pas vu venir&nbsp;:)</p>
|
||
<p>Dans les prochains articles, nous avons prévu de décrire les bonnes pratiques
|
||
rassemblées dans le protocole (ou <em>Cliquet</em>), certains points techniques précis
|
||
et de vous présenter notre vision via des exemples et&nbsp;tutoriaux.</p>
|
||
<p>À bientôt, donc&nbsp;!</p>
|
||
</div>
|
||
</content><category term="code"></category></entry><entry><title>Le secret du bonheur</title><link href="https://blog.notmyidea.org/le-secret-du-bonheur.html" rel="alternate"></link><published>2014-11-20T00:00:00+01:00</published><updated>2014-11-20T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2014-11-20:/le-secret-du-bonheur.html</id><summary type="html">
|
||
<p>Un enfant demande à son père&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Dis papa, quel est le secret pour être heureux&nbsp;?</p>
|
||
</blockquote>
|
||
<p>Sans dire un mot, le père demande à son fils de le suivre ; Ils sortent
|
||
de la maison, le père sur leur vieil âne et le fils suivant à&nbsp;pied.</p>
|
||
<p>Et les gens du village …</p></summary><content type="html">
|
||
<p>Un enfant demande à son père&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Dis papa, quel est le secret pour être heureux&nbsp;?</p>
|
||
</blockquote>
|
||
<p>Sans dire un mot, le père demande à son fils de le suivre ; Ils sortent
|
||
de la maison, le père sur leur vieil âne et le fils suivant à&nbsp;pied.</p>
|
||
<p>Et les gens du village de dire&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Mais quel mauvais père qui oblige ainsi son fils d&#8217;aller à pied&nbsp;!</p>
|
||
</blockquote>
|
||
<p>Le lendemain ils sortent de&nbsp;nouveau.</p>
|
||
<p>Le père ayant installé son fils sur l&#8217;âne et lui marchant à&nbsp;côté.</p>
|
||
<p>Les gens du village dirent alors&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Quel fils indigne, qui ne respecte pas son vieux père et le laisse
|
||
aller à pied&nbsp;!</p>
|
||
</blockquote>
|
||
<p>Le jour suivant, ils s&#8217;installent tous les deux sur l&#8217;âne avant de
|
||
quitter la maison. Les villageois commentèrent en disant&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Ils ne respectent pas leur bête à la surcharger ainsi&nbsp;!</p>
|
||
</blockquote>
|
||
<p>Le jour suivant, ils partirent en portant eux-mêmes leurs affaires,
|
||
l&#8217;âne trottinant derrière eux. Cette fois les gens du village y
|
||
trouvèrent encore à redire&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Voilà qu&#8217;ils portent eux-mêmes leurs bagages maintenant ! C&#8217;est le
|
||
monde à l&#8217;envers&nbsp;!</p>
|
||
</blockquote>
|
||
<p>De retour à la maison, le père dit à son fils&nbsp;:</p>
|
||
<blockquote>
|
||
<p>Tu me demandais l&#8217;autre jour le secret du bonheur. Peu importe ce que
|
||
tu fais, il y aura toujours quelqu&#8217;un pour y trouver à redire. Fais ce
|
||
qui te plaît et là tu seras vraiment&nbsp;heureux.</p>
|
||
</blockquote></content><category term="journal"></category></entry><entry><title>What’s Hawk and how to use it?</title><link href="https://blog.notmyidea.org/whats-hawk-and-how-to-use-it.html" rel="alternate"></link><published>2014-07-31T00:00:00+02:00</published><updated>2014-07-31T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2014-07-31:/whats-hawk-and-how-to-use-it.html</id><summary type="html">
|
||
<p>At Mozilla, we recently had to implement <a href="https://github.com/hueniverse/hawk">the Hawk authentication
|
||
scheme</a> for a number of projects,
|
||
and we came up creating two libraries to ease integration into pyramid
|
||
and node.js&nbsp;apps.</p>
|
||
<p>But maybe you don&#8217;t know&nbsp;Hawk.</p>
|
||
<p>Hawk is a relatively new technology, crafted by one of the …</p></summary><content type="html">
|
||
<p>At Mozilla, we recently had to implement <a href="https://github.com/hueniverse/hawk">the Hawk authentication
|
||
scheme</a> for a number of projects,
|
||
and we came up creating two libraries to ease integration into pyramid
|
||
and node.js&nbsp;apps.</p>
|
||
<p>But maybe you don&#8217;t know&nbsp;Hawk.</p>
|
||
<p>Hawk is a relatively new technology, crafted by one of the original
|
||
<a href="https://en.wikipedia.org/wiki/OAuth">OAuth</a> specification authors, that
|
||
intends to replace the 2-legged OAuth authentication scheme using a
|
||
simpler&nbsp;approach.</p>
|
||
<p>It is an authentication scheme for <span class="caps">HTTP</span>, built around <a href="https://en.wikipedia.org/wiki/Hmac"><span class="caps">HMAC</span>
|
||
digests</a> of requests and&nbsp;responses.</p>
|
||
<p>Every authenticated client request has an Authorization header
|
||
containing a <span class="caps">MAC</span> (Message Authentication Code) and some additional
|
||
metadata, then each server response to authenticated requests contains a
|
||
Server-Authorization header that authenticates the response, so the
|
||
client is sure it comes from the right&nbsp;server.</p>
|
||
<h2 id="exchange-of-the-hawk-id-and-hawk-key">Exchange of the hawk id and hawk&nbsp;key</h2>
|
||
<p>To sign the requests, a client needs to retrieve a token id and a token
|
||
key from the&nbsp;server.</p>
|
||
<p>Hawk itself does not define how these credentials should be exchanged
|
||
between the server and the client. The excellent team behind <a href="http://accounts.firefox.com">Firefox
|
||
Accounts</a> put together a scheme to do that,
|
||
which acts like the&nbsp;following:</p>
|
||
<div class="note">
|
||
|
||
<div class="admonition-title">
|
||
|
||
Note
|
||
|
||
</div>
|
||
|
||
All this derivation crazyness might seem a bit complicated, but don&#8217;t
|
||
worry, we put together some libraries that takes care of that for you
|
||
automatically.
|
||
|
||
If you are not interested into these details, you can directly jump to
|
||
the next section to see how to use the libraries.
|
||
|
||
</div>
|
||
|
||
<p>When your server application needs to send you the credentials, it will
|
||
return it inside a specific Hawk-Session-Token header. This token can be
|
||
derived to split this string in two values (hawk id and hawk key) that
|
||
you will use to sign your next&nbsp;requests.</p>
|
||
<p>In order to get the hawk credentials, you&#8217;ll need&nbsp;to:</p>
|
||
<p>First, do an <a href="http://en.wikipedia.org/wiki/HKDF"><span class="caps">HKDF</span> derivation</a> on the
|
||
given session token. You&#8217;ll need to use the following&nbsp;parameters:</p>
|
||
<div class="highlight"><pre><span></span><code>key_material = HKDF(hawk_session, &quot;&quot;, &#39;identity.mozilla.com/picl/v1/sessionToken&#39;, 32*2)
|
||
</code></pre></div>
|
||
|
||
<div class="note">
|
||
|
||
<div class="admonition-title">
|
||
|
||
Note
|
||
|
||
</div>
|
||
|
||
The `identity.mozilla.com/picl/v1/sessionToken` is a reference to this
|
||
way of deriving the credentials, not an actual <span class="caps">URL</span>.
|
||
|
||
</div>
|
||
|
||
<p>Then, the key material you&#8217;ll get out of the <span class="caps">HKDF</span> need to be separated
|
||
into two parts, the first 32 hex caracters are the hawk id, and the next
|
||
32 ones are the hawk&nbsp;key.</p>
|
||
<p>Credentials:</p>
|
||
<div class="highlight"><pre><span></span><code>javascript
|
||
credentials = {
|
||
&#39;id&#39;: keyMaterial[0:32],
|
||
&#39;key&#39;: keyMaterial[32:64],
|
||
&#39;algorithm&#39;: &#39;sha256&#39;
|
||
}
|
||
</code></pre></div>
|
||
|
||
<h2 id="httpie">Httpie</h2>
|
||
<p>To showcase APIs in the documentation, I like to use
|
||
<a href="https://github.com/jakubroztocil/httpie">httpie</a>, a curl-replacement
|
||
with a nicer <span class="caps">API</span>, built around <a href="http://python-requests.org">the python requests
|
||
library</a>.</p>
|
||
<p>Luckily, HTTPie allows you to plug different authentication schemes for
|
||
it, so <a href="https://github.com/mozilla-services/requests-hawk">I wrote a
|
||
wrapper</a> around
|
||
<a href="https://github.com/kumar303/mohawk">mohawk</a> to add hawk support to the
|
||
requests&nbsp;lib.</p>
|
||
<p>Doing hawk requests in your terminal is now as simple&nbsp;as:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>requests-hawk<span class="w"> </span>httpie
|
||
$<span class="w"> </span>http<span class="w"> </span>GET<span class="w"> </span>localhost:5000/registration<span class="w"> </span>--auth-type<span class="o">=</span>hawk<span class="w"> </span>--auth<span class="o">=</span><span class="s1">&#39;id:key&#39;</span>
|
||
</code></pre></div>
|
||
|
||
<p>In addition, it will help you to craft requests using the requests&nbsp;library:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">requests</span>
|
||
<span class="kn">from</span> <span class="nn">requests_hawk</span> <span class="kn">import</span> <span class="n">HawkAuth</span>
|
||
|
||
<span class="n">hawk_auth</span> <span class="o">=</span> <span class="n">HawkAuth</span><span class="p">(</span>
|
||
<span class="n">credentials</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;id&#39;</span><span class="p">:</span> <span class="nb">id</span><span class="p">,</span> <span class="s1">&#39;key&#39;</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="s1">&#39;algorithm&#39;</span><span class="p">:</span> <span class="s1">&#39;sha256&#39;</span><span class="p">})</span>
|
||
|
||
<span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/url&quot;</span><span class="p">,</span> <span class="n">auth</span><span class="o">=</span><span class="n">hawk_auth</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>Alternatively, if you don&#8217;t have the token id and key, you can pass the
|
||
hawk session token I talked about earlier and the lib will take care of
|
||
the derivation for&nbsp;you:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">hawk_auth</span> <span class="o">=</span> <span class="n">HawkAuth</span><span class="p">(</span>
|
||
<span class="n">hawk_session</span><span class="o">=</span><span class="n">resp</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;hawk-session-token&#39;</span><span class="p">],</span>
|
||
<span class="n">server_url</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">server_url</span>
|
||
<span class="p">)</span>
|
||
<span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/url&quot;</span><span class="p">,</span> <span class="n">auth</span><span class="o">=</span><span class="n">hawk_auth</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="integrate-with-python-pyramid-apps">Integrate with python pyramid&nbsp;apps</h2>
|
||
<p>If you&#8217;re writing pyramid applications, you&#8217;ll be happy to learn that
|
||
<a href="https://www.rfk.id.au/blog/">Ryan Kelly</a> put together a library that
|
||
makes Hawk work as an Authentication provider for them. I&#8217;m chocked how
|
||
simple it is to use&nbsp;it.</p>
|
||
<p>Here is a demo of how we implemented it for&nbsp;Daybed:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">pyramid_hawkauth</span> <span class="kn">import</span> <span class="n">HawkAuthenticationPolicy</span>
|
||
|
||
<span class="n">policy</span> <span class="o">=</span> <span class="n">HawkAuthenticationPolicy</span><span class="p">(</span><span class="n">decode_hawk_id</span><span class="o">=</span><span class="n">get_hawk_id</span><span class="p">)</span>
|
||
<span class="n">config</span><span class="o">.</span><span class="n">set_authentication_policy</span><span class="p">(</span><span class="n">authn_policy</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>The get_hawk_id function is a function that takes a request and a
|
||
tokenid and returns a tuple of (token_id,&nbsp;token_key).</p>
|
||
<p>How you want to store the tokens and retrieve them is up to you. The
|
||
default implementation (e.g. if you don&#8217;t pass a decode_hawk_id
|
||
function) decodes the key from the token itself, using a master secret
|
||
on the server (so you don&#8217;t need to store&nbsp;anything).</p>
|
||
<h2 id="integrate-with-nodejs-express-apps">Integrate with node.js Express&nbsp;apps</h2>
|
||
<p>We had to implement Hawk authentication for two node.js projects and
|
||
finally came up factorizing everything in a library for express, named
|
||
<a href="https://github.com/mozilla-services/express-hawkauth">express-hawkauth</a>.</p>
|
||
<p>In order to plug it in your application, you&#8217;ll need to use it as a&nbsp;middleware:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">javascript</span>
|
||
<span class="k">var</span><span class="w"> </span><span class="n">express</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">require</span><span class="p">(</span><span class="s2">&quot;express&quot;</span><span class="p">);</span>
|
||
<span class="k">var</span><span class="w"> </span><span class="n">hawk</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">require</span><span class="p">(</span><span class="s2">&quot;express-hawkauth&quot;</span><span class="p">);</span>
|
||
<span class="n">app</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">express</span><span class="p">();</span>
|
||
|
||
<span class="k">var</span><span class="w"> </span><span class="n">hawkMiddleware</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">hawk</span><span class="o">.</span><span class="n">getMiddleware</span><span class="p">({</span>
|
||
<span class="w"> </span><span class="n">hawkOptions</span><span class="p">:</span><span class="w"> </span><span class="p">{},</span>
|
||
<span class="w"> </span><span class="n">getSession</span><span class="p">:</span><span class="w"> </span><span class="n">function</span><span class="p">(</span><span class="n">tokenId</span><span class="p">,</span><span class="w"> </span><span class="n">cb</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="k">pass</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">cb</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">key</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">algorithm</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">the</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">token</span><span class="w"> </span><span class="n">id</span><span class="o">.</span><span class="w"> </span><span class="n">First</span><span class="w"> </span><span class="n">argument</span><span class="w"> </span><span class="n">of</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">callback</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">potential</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">error</span><span class="o">.</span>
|
||
<span class="w"> </span><span class="n">cb</span><span class="p">(</span><span class="nb nb-Type">null</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="n">key</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;key&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">algorithm</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;sha256&quot;</span><span class="p">});</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="n">createSession</span><span class="p">:</span><span class="w"> </span><span class="n">function</span><span class="p">(</span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">cb</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">which</span><span class="w"> </span><span class="n">stores</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">session</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">key</span><span class="o">.</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">Argument</span><span class="w"> </span><span class="n">returned</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">potential</span><span class="w"> </span><span class="n">error</span><span class="o">.</span>
|
||
<span class="w"> </span><span class="n">cb</span><span class="p">(</span><span class="nb nb-Type">null</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="n">setUser</span><span class="p">:</span><span class="w"> </span><span class="n">function</span><span class="p">(</span><span class="n">req</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="n">tokenId</span><span class="p">,</span><span class="w"> </span><span class="n">cb</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">A</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">uses</span><span class="w"> </span><span class="n">req</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">hawkId</span><span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="n">they</span><span class="s1">&#39;re known so</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">that</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">tweak</span><span class="w"> </span><span class="n">it</span><span class="o">.</span><span class="w"> </span><span class="n">For</span><span class="w"> </span><span class="n">instance</span><span class="p">,</span><span class="w"> </span><span class="n">you</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">store</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">tokenId</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">the</span>
|
||
<span class="w"> </span><span class="o">//</span><span class="w"> </span><span class="n">user</span><span class="o">.</span>
|
||
<span class="w"> </span><span class="n">req</span><span class="o">.</span><span class="n">user</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tokenId</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">});</span>
|
||
|
||
<span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/hawk-enabled-endpoint&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">hawkMiddleware</span><span class="p">);</span>
|
||
</code></pre></div>
|
||
|
||
<p>If you pass the createSession parameter, all non-authenticated requests
|
||
will create a new hawk session and return it with the response, in the
|
||
Hawk-Session-Token&nbsp;header.</p>
|
||
<p>If you want to only check a valid hawk session exists (without creating
|
||
a new one), just create a middleware which doesn&#8217;t have any
|
||
createSession parameter&nbsp;defined.</p>
|
||
<h2 id="some-reference-implementations">Some reference&nbsp;implementations</h2>
|
||
<p>As a reference, here is how we&#8217;re using the libraries I&#8217;m talking about,
|
||
in case that helps you to integrate with your&nbsp;projects.</p>
|
||
<ul>
|
||
<li>The Mozilla Loop server <a href="https://github.com/mozilla-services/loop-server/blob/master/loop/index.js#L70-L133">uses hawk as authentication once you&#8217;re
|
||
logged in with a valid BrowserID
|
||
assertion</a>;
|
||
request, to keep a session between client and&nbsp;server;</li>
|
||
<li><a href="https://github.com/spiral-project/daybed/commit/f178b4e43015fa077430798dcd3d0886c7611caf">I recently added hawk support on the Daybed
|
||
project</a>
|
||
(that&#8217;s a pyramid / cornice)&nbsp;app.</li>
|
||
<li>It&#8217;s also interesting to note that Kumar put together <a href="http://hawkrest.readthedocs.org/en/latest/">hawkrest, for
|
||
the django rest&nbsp;framework</a></li>
|
||
</ul></content><category term="code"></category></entry><entry><title>Quel métier, quelle utilité ?</title><link href="https://blog.notmyidea.org/quel-metier-quelle-utilite.html" rel="alternate"></link><published>2014-07-29T00:00:00+02:00</published><updated>2014-07-29T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2014-07-29:/quel-metier-quelle-utilite.html</id><summary type="html">
|
||
<p>Aujourd&#8217;hui, mon métier est d&#8217;être développeur d&#8217;applications. Imaginer
|
||
des solutions techniques pour faire marcher des logiciels, puis écrire
|
||
les lignes de code&nbsp;nécessaires.</p>
|
||
<p>Être Développeur n&#8217;est pas un métier qui a du sens en lui même (comme
|
||
peut l&#8217;être le métier d&#8217;instituteur/rice par …</p></summary><content type="html">
|
||
<p>Aujourd&#8217;hui, mon métier est d&#8217;être développeur d&#8217;applications. Imaginer
|
||
des solutions techniques pour faire marcher des logiciels, puis écrire
|
||
les lignes de code&nbsp;nécessaires.</p>
|
||
<p>Être Développeur n&#8217;est pas un métier qui a du sens en lui même (comme
|
||
peut l&#8217;être le métier d&#8217;instituteur/rice par exemple). Tout comme
|
||
lorsque l&#8217;on est écrivain il est important de se poser des questions sur
|
||
les textes que l&#8217;on produit, pour qui et dans quel but; il est important
|
||
de se questionner sur l&#8217;utilité du métier de développeur, et sur
|
||
l&#8217;utilisation des contenus&nbsp;produits.</p>
|
||
<p>Je suis un développeur parce que je défends certaines valeurs. Les
|
||
valeurs du partage de connaissances, de la collaboration, et de&nbsp;l&#8217;émancipation.</p>
|
||
<p>Je suis aussi développeur parce qu&#8217;il me plait de créer des contenus à
|
||
partir de &#8220;pas grand chose&#8221;. La <em>magie</em> de la création logicielle
|
||
m&#8217;anime, parce que j&#8217;ai l&#8217;impression qu&#8217;il est possible de faire des
|
||
choses géniales à partir de ce &#8220;pas grand chose&#8221;. Donnez moi un
|
||
ordinateur et je vous crée une application de partage de semences
|
||
paysannes. Un peu comme il est possible de donner une feuille de papier
|
||
à un dessinateur pour se retrouver avec un univers magnifique couché
|
||
sur&nbsp;papier.</p>
|
||
<p>Je me rends compte qu&#8217;au fur et à mesure des années, je me laisse
|
||
ramollir, absorber par le quotidien et me retrouve à ne plus me poser de
|
||
questions quant à l&#8217;utilité de mon métier. Pourquoi est-ce que je code ?
|
||
À qui cela sert il ? Quelle est ma motivation réelle&nbsp;?</p>
|
||
<p>En travaillant pour Mozilla, on pourrait croire que ce problème est
|
||
résolu de fait, puisque après tout, Mozilla, c&#8217;est les &#8220;protecteurs du
|
||
web&#8221;, des gentils, et qu&#8217;on essaye nécessairement de faire les choses&nbsp;bien…</p>
|
||
<h2 id="lomnipresence-technologique">L&#8217;omniprésence&nbsp;technologique</h2>
|
||
<p>Je ne suis pas convaincu qu&#8217;utiliser la technologie de la manière dont
|
||
on le fait actuellement est systématiquement une bonne&nbsp;chose:</p>
|
||
<p>Depuis 2 ans quasiment maintenant, Mozilla travaille sur un système
|
||
d&#8217;exploitation mobile, un remplaçant pour les iphones et androides, qui
|
||
utilise cette fois ci les technologies du web. Les avantages sont
|
||
multiples, et le principal intérêt est de faire un téléphone qui ne soit
|
||
pas au service des &#8220;gros&#8221; du Web mondial (Google et&nbsp;Apple).</p>
|
||
<p>Ces &#8220;ordiphones&#8221; à destination des pays dits &#8220;émergents&#8221; sont d&#8217;ailleurs
|
||
construits à faible coût — toujours de manière honteuse, pour la plupart
|
||
en chine, dans les mêmes chaines de production que les autres
|
||
téléphones, mais c&#8217;est un autre&nbsp;débat.</p>
|
||
<p>L&#8217;idée, assez intéressante d&#8217;un point de vue marché (les pays en
|
||
question n&#8217;ayant que peu de périphériques actuellement semblent un
|
||
terrain propice à la diffusion des &#8220;ordiphones&#8221;), est de donner accès à
|
||
la technologie, au Web à ces pays&nbsp;émergents.</p>
|
||
<p>L&#8217;accès à la technologie pour tous me semble relever de la chimère
|
||
productiviste: je conçois que la technologie puisse être un pas en avant
|
||
assez fou, notamment lorsque l&#8217;on connaît la richesse des contenus qu&#8217;on
|
||
peut trouver sur le web, mais cette richesse vient aussi avec un certain
|
||
coût, que nous avons actuellement du mal, en tant qu&#8217;utilisateurs, à
|
||
contrôler et à mesurer. Les gens sont beaucoup beaucoup trop&nbsp;connectés.</p>
|
||
<p>Je le suis par exemple bien plus souvent que ce que je voudrais
|
||
l&#8217;admettre, que ce soit pour regarder un film, lire mes emails,
|
||
communiquer avec des amis, faire de l&#8217;associatif, écrire du code, des
|
||
billets sur ces&nbsp;carnets…</p>
|
||
<p>Cette technologie, omniprésente dans nos vies, je ne sais pas si c&#8217;est
|
||
un futur que je souhaite&nbsp;partager.</p>
|
||
<p>Pour prendre un autre exemple, les bienfaits de la technologie ne
|
||
viennent pas seuls. Les réseaux sociaux, qui constituent une bonne part
|
||
de l&#8217;utilisation du Web, relèvent du culte de la personnalité, de
|
||
l&#8217;individualisme, et ce n&#8217;est pas ce développement que je souhaite pour
|
||
notre&nbsp;société.</p>
|
||
<p>L&#8217;idée de base du Web, le fait de faire une toile de connaissances
|
||
ouverte et partagée entre tous est en train, petit à petit, de glisser
|
||
vers l&#8217;idée d&#8217;un outil de relai de l&#8217;information, où tout va vite, où
|
||
l&#8217;on ne prends guère plus le temps de lire autre chose que les titres
|
||
des quotidiens, ou des &#8220;tweets&#8221; de cent vingt&nbsp;caractères…</p>
|
||
<h2 id="des-outils-utiles">Des outils&nbsp;utiles</h2>
|
||
<p>Bon an, mal an, je pense quand même que la technologie puisse être un
|
||
vecteur d&#8217;émancipation. Plus spécifiquement, je crois qu&#8217;il ne faut pas
|
||
laisser l&#8217;utilisation de la technologie aux &#8220;gros&#8221;, aux entreprises, aux
|
||
états ou&nbsp;&#8220;spécialistes&#8221;.</p>
|
||
<p>Il est important de ne pas laisser ceux que l&#8217;on combat s&#8217;emparer des
|
||
&#8220;outils du pouvoir&#8221;. La science, la technologie ou les médias sont
|
||
autant de champs qu&#8217;il est important de défendre, de conserver, de&nbsp;s&#8217;approprier.</p>
|
||
<p>Un des objectifs que je me fixe, pour les années à venir, ce que j&#8217;ai
|
||
envie de créer, c&#8217;est à la fois des outils utiles pour les
|
||
organisations, mais aussi éduquer à ces&nbsp;outils.</p>
|
||
<p>Parce que l&#8217;éducation populaire ne s&#8217;arrête pas aux frontières du
|
||
numérique, parce qu&#8217;il est important de se battre avec les mêmes outils
|
||
que ce monde que l&#8217;on cherche parfois à&nbsp;combattre.</p>
|
||
<p>Les outils sur lesquels j&#8217;ai envie d&#8217;être amené à travailler sont des
|
||
outils qui favorisent et questionnent la&nbsp;collaboration.</p>
|
||
<p>Des outils comme etherpad par exemple, révolutionnent la manière de
|
||
prendre des notes en commun, et il reste énormément à faire sur le web à
|
||
ce&nbsp;propos.</p>
|
||
<p>Nombre d&#8217;associations me demandent de plus en plus souvent ce qu&#8217;il en
|
||
est de Daybed, et de quand est-ce qu&#8217;on va pouvoir utiliser un système
|
||
de génération de formulaires en ligne, qui ne soit pas centré sur les
|
||
services de&nbsp;google…</p>
|
||
<p>Allez, au boulot&nbsp;!</p>
|
||
<p><span class="caps">PS</span>: je me rends compte après relecture que ce billet fait echo à un
|
||
billet que j&#8217;ai écris juste alors que je terminais mes études, <a href="https://blog.notmyidea.org/travailler-moins-pour-mieux-travailler.html">sur le
|
||
sens du travail et de
|
||
l&#8217;informatique</a>, ça
|
||
fait du bien&nbsp;:)</p></content><category term="journal"></category></entry><entry><title>Retours sur deux ans à Mozilla</title><link href="https://blog.notmyidea.org/retours-sur-deux-ans-a-mozilla.html" rel="alternate"></link><published>2014-07-29T00:00:00+02:00</published><updated>2014-07-29T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2014-07-29:/retours-sur-deux-ans-a-mozilla.html</id><summary type="html">
|
||
<p><em>Ça fait un bail que j&#8217;ai cet article en cours de rédaction, et je me dis que je dois le poster maintenant, sinon je ne le ferais jamais (saloperie de perfectionnisme&nbsp;?)</em></p>
|
||
<p>Il y à deux ans et demi, en décembre, je commençais à travailler chez
|
||
Mozilla, dans l&#8217;équipe …</p></summary><content type="html">
|
||
<p><em>Ça fait un bail que j&#8217;ai cet article en cours de rédaction, et je me dis que je dois le poster maintenant, sinon je ne le ferais jamais (saloperie de perfectionnisme&nbsp;?)</em></p>
|
||
<p>Il y à deux ans et demi, en décembre, je commençais à travailler chez
|
||
Mozilla, dans l&#8217;équipe &#8220;Cloud&nbsp;Services&#8221;.</p>
|
||
<p>Depuis, énormément de choses ont évoluées, tant en ce qui concerne les
|
||
objectifs de Mozilla (avec l&#8217;arrivée de FirefoxOS) que le travail que
|
||
j&#8217;effectue au jour le jour. Pour autant, mes objectifs personnels
|
||
restent&nbsp;intacts.</p>
|
||
<p>Deux ans ça parait énorme, c&#8217;est le temps le plus long que j&#8217;ai passé à
|
||
travailler sur un projet, avec quasiment les mêmes personnes. Si vous
|
||
suivez un peu ces carnets, vous savez surement que j&#8217;ai beaucoup
|
||
travaillé avec <a href="https://ziade.org">Tarek</a> par&nbsp;exemple.</p>
|
||
<p>Ça a été (et c&#8217;est toujours) un réel plaisir de bosser avec la personne
|
||
dont j&#8217;avais lu les livres pour apprendre le python, merci&nbsp;!</p>
|
||
<h2 id="services">Services</h2>
|
||
<p>Le principal de mon travail a été de construire des outils. Je suis le
|
||
mainteneur de <a href="https://github.com/mozilla-services/cornice">Cornice</a>, un
|
||
utilitaire qui vient se greffer par dessus <a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">le framework python
|
||
pyramid</a> pour
|
||
vous simplifier la vie et créer des services web; J&#8217;ai travaillé un peu
|
||
sur un outil de gestion des processus nommé
|
||
<a href="https://github.com/mozilla-services/circus">Circus</a>, et également sur
|
||
un outil de montée en charge dénommé
|
||
<a href="https://github.com/mozilla-services/loads">Loads</a></p>
|
||
<p>Au tout début, j&#8217;ai travaillé sur un concept de <a href="https://github.com/mozilla-services/tokenserver">serveur de
|
||
tokens</a>. L&#8217;idée était
|
||
de désolidariser l&#8217;authentification des services web des services eux&nbsp;mêmes.</p>
|
||
<p>L&#8217;idée est (je pense) bonne mais le service n&#8217;a pas été utilisé durant
|
||
plus de deux ans. La raison étant principalement que Sync, pour lequel
|
||
le serveur de tokens a été écrit, a subi des changements majeurs (qui
|
||
sont rentrés en production il y a quelques&nbsp;semaines)</p>
|
||
<p>Circus est né de besoins découverts via le token server, et il m&#8217;a
|
||
personnellement beaucoup appris. Le token server est finalement utilisé
|
||
dans la nouvelle version de Sync qui est rentrée en production il y a&nbsp;peu.</p>
|
||
<h2 id="marketplace-chouette-on-va-casser-du-serveur">Marketplace (&#8220;chouette, on va casser du&nbsp;serveur&#8221;)</h2>
|
||
<p>Après 6 mois à travailler à Services, Tarek et moi avons commencé à
|
||
rejoindre l&#8217;équipe du Marketplace pour faire un travail d&#8216;&#8220;audit de&nbsp;performance&#8221;.</p>
|
||
<p>L&#8217;idée était de prêter main forte à l&#8217;équipe du marketplace, mais les
|
||
détails étaient alors assez flous. Le code est assez indigeste au
|
||
premier abord, ce qui m&#8217;avait alors pas mal refroidi. La raison
|
||
principale étant que le code est utilisé à la fois par
|
||
addons.mozilla.org et par marketplace.firefox.com, rendant les choses
|
||
souvent un peu plus compliquées qu&#8217;il ne&nbsp;faudrait.</p>
|
||
<p>Cet &#8220;audit&#8221; a été l&#8217;occasion de travailler sur des outils de montée en
|
||
charge assez sympa, qui ont donné naissance à un projet qu&#8217;on utilise
|
||
assez souvent maintenant, <a href="">Loads</a>.</p>
|
||
<p>Énormément d&#8217;efforts sont fait pour aller dans la bonne direction et
|
||
faire en sorte que le code soit plus facile à maintenir et que le projet
|
||
soit plus facile à aborder. D&#8217;ailleurs, pas mal de copains djangonautes
|
||
français travaillent dessus (salut <a href="http://virgule.net">Mathieu</a>, Yohan,
|
||
<a href="http://larlet.fr">David</a> et <a href="http://mathieu.agopian.info">Mathieu
|
||
Agopian</a>!)</p>
|
||
<p>Une partie de notre plan a été de sortir certaines fonctionnalités du
|
||
code actuel, pour en faire quelque chose de plus facile à maintenir et
|
||
de moins&nbsp;imbriqué.</p>
|
||
<h2 id="la-communaute">La&nbsp;Communauté</h2>
|
||
<p><a href="">Circus</a> et <a href="">Cornice</a> sont deux outils qui semblent utiles à la
|
||
communauté. J&#8217;ai eu des retours très positifs sur Cornice, et j&#8217;essaye
|
||
de le faire évoluer dans la direction qui me semble&nbsp;propice.</p>
|
||
<p>D&#8217;ailleurs, Cornice est utilisé (par <a href="http://blog.mathieu-leplatre.info/pages/about.html">Mathieu
|
||
L.</a> — encore un —,
|
||
<a href="http://twitter.com/natim">Rémy</a> et moi) actuellement pour coder
|
||
<a href="https://github.com/spiral-project/daybed">Daybed</a> un service de
|
||
validation de formulaires, mais ça sera l&#8217;objet d&#8217;un futur&nbsp;billet.</p>
|
||
<p>Circus commence à recevoir des contributions de plus en plus
|
||
intéressantes, et à être utilisé en interne chez nous et chez d&#8217;autres,
|
||
donc c&#8217;est une extrêmement bonne&nbsp;nouvelle.</p>
|
||
<h2 id="talkilla-loop">Talkilla /&nbsp;Loop</h2>
|
||
<p>Après quelques temps, j&#8217;avais envie d&#8217;apprendre de nouveau. Python c&#8217;est
|
||
génial mais c&#8217;était devenu ma &#8220;zone de confort&#8221;. J&#8217;adore découvrir des
|
||
choses, donc c&#8217;était le moment de faire en sorte que ça&nbsp;continue!</p>
|
||
<p>C&#8217;était aussi l&#8217;occasion de travailler avec
|
||
<a href="https://nicolas.perriault.net/">Nicolas</a> et
|
||
<a href="http://monkeypatch.me/blog/">Romain</a>. Je suivais le projet Talkilla de
|
||
plus ou moins loin depuis quelques mois, c&#8217;était donc l&#8217;occasion à ne
|
||
pas&nbsp;manquer.</p>
|
||
<p>En rentrant dans cette équipe, je cherchais principalement à avoir un
|
||
projet visible pour les utilisateurs finaux. Refaire un peu de frontend,
|
||
apprendre à faire du JavaScript propre et découvrir de nouvelles&nbsp;personnes.</p>
|
||
<p>J&#8217;y ai aussi récupéré une équipe qui essaye de suivre les principes de
|
||
l&#8217;agilité et qui est sur mon fuseau horaire (pour la plupart). Le&nbsp;rêve.</p>
|
||
<p>L&#8217;idée derrière Talkilla est d&#8217;utiliser la technologie de communication
|
||
pair à pair dans les navigateurs (WebRTC) pour faire des appels audio /
|
||
vidéo. En d&#8217;autres termes, c&#8217;est un peu transformer votre firefox en
|
||
téléphone, sauf que personne ne peut espionner ce qui se passe entre
|
||
vous et l&#8217;autre bout du&nbsp;fil.</p>
|
||
<p>A peine arrivé dans le projet (peut-être un mois et quelques après mon
|
||
débarquement) le choix a été fait de tout réécrire depuis zéro, dans un
|
||
projet qui se nomme actuellement &#8220;Loop&#8221;, qui veut proposer la même
|
||
chose, mais inclus directement dans&nbsp;Firefox.</p>
|
||
<p>C&#8217;est en bonne voie, on a quelque chose qui fonctionne dans nightly, et
|
||
le code du serveur fonctionne pas mal. Le code du serveur est ici:
|
||
<a href="https://github.com/mozilla-services/loop-server">https://github.com/mozilla-services/loop-server</a>.</p>
|
||
<p>Un client est en train d&#8217;être implémenté dans Firefox et un autre en
|
||
tant qu&#8217;application pour FirefoxOS. Le boulot ne s&#8217;arrête pas de
|
||
pleuvoir, mais je pense qu&#8217;on va dans une direction&nbsp;intéressante.</p>
|
||
<p>Pour être complètement terminé, il faudrait qu&#8217;on soit capable de se
|
||
passer complètement de notre provider, TokBox (que l&#8217;on utilise en tant
|
||
que relai média), pour que n&#8217;importe qui puisse choisir d&#8217;utiliser son
|
||
propre serveur <span class="caps">STUN</span> / <span class="caps">TURN</span> et installe son serveur loop chez&nbsp;lui.</p>
|
||
<h3 id="le-travail-a-distance">Le travail à&nbsp;distance</h3>
|
||
<p>Quand j&#8217;ai commencé à travailler à Mozilla, j&#8217;ai décidé de venir
|
||
m&#8217;installer à Paris. La plupart des personnes de mon entourage ont
|
||
d&#8217;ailleurs fait des gros yeux, parce qu&#8217;ils connaissaient mon avis sur
|
||
la ville en question, mais casser des préjugés n&#8217;est jamais une mauvaise&nbsp;chose.</p>
|
||
<p>Après deux ans passés à Paris, j&#8217;ai décidé de partir m&#8217;installer à
|
||
Rennes, puisque de toute manière, la plupart de mon travail s&#8217;effectue
|
||
au jour le jour à distance. En d&#8217;autres termes, la plupart de mon équipe
|
||
n&#8217;est pas à coté de moi quand je travaille, ce qui veut dire que je peux
|
||
travailler depuis n&#8217;importe&nbsp;où.</p>
|
||
<p>Ce qui fonctionne pour moi, c&#8217;est de ne quasiment jamais travailler
|
||
depuis la maison. J&#8217;utilise <a href="http://www.lacantine-rennes.net/">un espace de
|
||
coworking</a> qui est un moyen de garder
|
||
ma vie perso séparée de ma vie privée et de rencontrer des gens
|
||
passionnés par ce qu&#8217;ils&nbsp;font.</p>
|
||
<p>Depuis que je suis arrivé à Rennes, Rémy a commencé à travailler avec
|
||
moi, et c&#8217;est un réel bonheur que de pouvoir partager des journées de
|
||
travail. On &#8220;pair-prog&#8221; énormément et j&#8217;ai l&#8217;impression d&#8217;avoir un boost
|
||
dans ma productivité&nbsp;quotidienne.</p>
|
||
<h3 id="enseignements">Enseignements</h3>
|
||
<p>Mozilla est ma première expérience professionnelle, et par conséquent,
|
||
je manque nécessairement de recul sur ce qui est acceptable et ce qui ne
|
||
l&#8217;est pas. D&#8217;une manière générale, avoir un environnement de travail
|
||
basé sur la confiance est réellement appréciable (La première réaction
|
||
des gens quand je dis que je peux travailler à distance, c&#8217;est de me
|
||
demander comment ils font pour être sur que je travaille. Et la réponse
|
||
est… il n&#8217;y en a&nbsp;pas).</p>
|
||
<p>J&#8217;ai encore un peu de mal à savoir quels indicateurs utiliser pour
|
||
savoir si je suis &#8220;productif&#8221; ou non, mais j&#8217;ai globalement l&#8217;impression
|
||
que je manque de concentration et de discipline: beaucoup
|
||
d&#8217;interruptions n&#8217;aident pas à se&nbsp;concentrer.</p>
|
||
<p>La motivation fluctue aussi énormément: un jour on est super motivé, un
|
||
autre c&#8217;est juste impossible de la trouver. Après quelques
|
||
expérimentations, le mieux (pour moi) est d&#8217;avoir des horaires fixes,
|
||
pour pouvoir séparer le travail du reste, de ne pas hésiter à faire des
|
||
pauses et d&#8217;écouter un peu ses envies et son corps (si je suis crevé, ça
|
||
ne sert à rien de se lever pour aller travailler, il vaut mieux se
|
||
reposer un peu pour être plus efficace ensuite, par&nbsp;exemple).</p>
|
||
<p>J&#8217;ai essayé de tirer quelques enseignements de ces deux&nbsp;années:</p>
|
||
<h2 id="malheureusement-le-code-nest-pas-propre">Malheureusement, le code n&#8217;est pas&nbsp;propre</h2>
|
||
<p>Je me rends compte que bien souvent je suis assez déçu de la qualité du
|
||
code que je regarde. Principalement parce que je ne suis pas capable de
|
||
le comprendre rapidement. Spécifiquement, ça m&#8217;est arrivé avec certaines
|
||
parties de <a href="https://github.com/mozilla/zamboni">Zamboni</a>, le code du
|
||
<a href="http://marketplace.firefox.com">Marketplace</a> dont je parlais plus haut,
|
||
avec certaines parties de Talkilla ou alors le code de Firefox lui&nbsp;même.</p>
|
||
<p>C&#8217;était extrêmement frustrant pour moi de découvrir que le code écrit à
|
||
Mozilla n&#8217;était pas exemplaire. Tout le code qui est ajouté à l&#8217;heure
|
||
actuelle est revu, corrigé et validé par des pairs, mais un certain
|
||
nombre de projets ont un historique assez lourd qui rends leur structure&nbsp;complexe.</p>
|
||
<p>Je réalise donc que mon travail n&#8217;est pas uniquement de savoir écrire du
|
||
code propre, mais également de réussir à comprendre du code que je
|
||
considère comme &#8220;sale&#8221; (quitte à l&#8217;améliorer au passage&nbsp;!).</p>
|
||
<p>Et c&#8217;est pas du gâteau; je m&#8217;attendais à réussir à comprendre des
|
||
projets complexes facilement, mais aucun miracle de ce coté là. Il faut
|
||
réussir à rester concentré pendant suffisamment longtemps pour pouvoir
|
||
tirer tous les fils et commencer à démêler… Pas facile&nbsp;!</p>
|
||
<h2 id="apprendre-est-un-processus-actif">Apprendre est un processus&nbsp;actif</h2>
|
||
<p>Il est facile de passer à coté de l&#8217;apprentissage. Être entouré de gens
|
||
talentueux ne suffit pas pour continuer à&nbsp;apprendre.</p>
|
||
<p>Savoir reconnaitre un échec est nécessaire. Dire que l&#8217;on comprends pour
|
||
éviter de passer pour un idiot est un biais qui se prends assez
|
||
rapidement, et qu&#8217;il faut éviter à tout&nbsp;prix.</p>
|
||
<p>Surtout au début, c&#8217;était une erreur que je faisais énormément, une
|
||
question d&#8217;égo&nbsp;probablement.</p>
|
||
<p>Il y a une espèce de honte de ne pas savoir, alors que tout le monde
|
||
autour sait ou en tout cas semble savoir. Bien souvent, les gens autour
|
||
ne savent pas non plus, ce qui mène à des discussions de comptoir, sans
|
||
trop savoir&nbsp;pourquoi.</p>
|
||
<p>Connaître ses limites techniques est un bon début pour pouvoir les
|
||
surpasser. Chercher à les rencontrer est un processus&nbsp;actif.</p>
|
||
<p>Le manque de temps m&#8217;empêche bien souvent de pouvoir prendre un livre
|
||
technique et de pouvoir l&#8217;apprécier. Je ne sais pas exactement pourquoi,
|
||
peut être par sur-dose, mais je n&#8217;ai ouvert que quelques rares livres
|
||
techniques durant ces deux années. Et j&#8217;aimerais bien que ça change&nbsp;!</p>
|
||
<h2 id="assez-bien-est-suffisant"><span class="dquo">&#8220;</span>Assez bien&#8221; est&nbsp;suffisant</h2>
|
||
<p>La culture de l&#8217;excellence se mets parfois au milieu du chemin. On
|
||
oublie souvent que &#8220;le mieux est l&#8217;ennemi du&nbsp;bien&#8221;.</p>
|
||
<p>Rien ne sert de faire des commits parfaits tout le temps. Quand j&#8217;ai
|
||
besoin de &#8220;hacker&#8221; sur un projet, je ne voulais d&#8217;abord pas tout péter,
|
||
par peur de ne plus m&#8217;y&nbsp;retrouver.</p>
|
||
<p>Mon approche actuelle est bien différente: on mets les mains dans le
|
||
cambouis jusqu&#8217;à ce que ça marche, et ensuite on répare les dégâts.
|
||
Enfin… dans une certaine mesure hein&nbsp;!</p>
|
||
<h2 id="ecrire-des-boites-a-outils-et-non-pas-des-frameworks">Écrire des boites à outils et non pas des&nbsp;frameworks</h2>
|
||
<p>Écrire des frameworks force les utilisateurs à les utiliser, et à les
|
||
connaitre dans les moindres recoins. Heureusement, il existe déjà
|
||
énormément de frameworks qui pour la plupart font très bien leur
|
||
travail. Ce qui nous manque ce n&#8217;est pas plus de frameworks, mais bel et
|
||
bien plus de boites à&nbsp;outils.</p>
|
||
<p>Une boite à outil prends un problème bien défini et propose une solution
|
||
pour ce problème. Une boite à outils est, en mon sens, ce qu&#8217;on appelle
|
||
une bibliothèque. Pas besoin de réécrire tout votre projet pour utiliser
|
||
ma nouvelle bibliothèque afin de profiter des fonctionnalités qu&#8217;elle
|
||
apporte (alors que c&#8217;est le cas avec un framework,&nbsp;justement).</p>
|
||
<h2 id="etre-le-moteur-de-son-propre-changement">Être le moteur de son propre&nbsp;changement</h2>
|
||
<p>Facile à dire, héhé ! D&#8217;une manière générale, je me rends compte qu&#8217;il
|
||
est facile de se plaindre sans pour autant être moteur du changement que
|
||
l&#8217;on souhaite voir&nbsp;arriver.</p>
|
||
<p>Ça vaut le coup de se donner la peine de faire changer les choses,
|
||
surtout à Mozilla, parce que le changement n&#8217;est pas seulement vu d&#8217;un
|
||
mauvais&nbsp;œil.</p>
|
||
<p>Pour que les choses évoluent, il faut être force de proposition. Se
|
||
plaindre n&#8217;a jamais servi à rien si ce n&#8217;est pas suivi d&#8217;actes&nbsp;;)</p>
|
||
<p>Je dis de temps en temps que Mozilla est une &#8220;do-o-cratie&#8221; (celui qui
|
||
fait à raison), et je le pense de plus en plus. Quand j&#8217;ai envie que
|
||
quelque chose soit fait, et bah… il faut le faire&nbsp;!</p>
|
||
<h2 id="ne-pas-chercher-a-avoir-raison">Ne pas chercher à avoir&nbsp;raison</h2>
|
||
<p>Peu importe qui a raison, l&#8217;important n&#8217;est pas de chercher à montrer
|
||
que tu sais, mais de trouver ce qui est juste. Ça parait peut être
|
||
évident, mais bien souvent on cherche à se mettre en avant, au
|
||
détriment du projet… Allez, gardons nos égos de coté&nbsp;;)</p>
|
||
<h2 id="arreter-le-negativisme">Arrêter le&nbsp;négativisme</h2>
|
||
<p>Il est très facile de se laisser embarquer dans le négativisme. Il y a
|
||
toujours des choses qui ne vont pas, et probablement il y en aura
|
||
toujours. Ce ne sont pas des raisons suffisantes pour perdre le moral.
|
||
Identifier les points faibles est important est permet de savoir ce
|
||
qu&#8217;il est nécessaire d&#8217;améliorer, mais regarder les choses du coté
|
||
positif (et il y en a nécessairement un !) est indispensable&nbsp;!</p>
|
||
<p>À plusieurs reprises je me suis retrouvé dans des crises de négativisme,
|
||
pour un tas de raisons différentes. La meilleure manière de s&#8217;en sortir:
|
||
en causer et trouver des solutions, prendre le problème à bras le corps,
|
||
et ne pas considérer que c&#8217;est un problème sur lequel on a aucune prise&nbsp;possible.</p>
|
||
<h3 id="la-suite">La suite&nbsp;?</h3>
|
||
<p>Je n&#8217;ai aucune idée d&#8217;à quoi va ressembler la suite, et c&#8217;est justement
|
||
ce que j&#8217;apprécie et qui m&#8217;effraie en même&nbsp;temps…</p>
|
||
<p>Je fais actuellement énormément de Javascript et je travaille sur des
|
||
projets qui semblent avoir plus de sens qu&#8217;avant (même si je vois déjà
|
||
des choses que je souhaiterais améliorer, mais chaque chose en son
|
||
temps). Donc techniquement j&#8217;apprends et dans ma quête de faire des
|
||
produits qui touchent un&nbsp;utilisateur.</p>
|
||
<p>Depuis quelques semaines, je peux travailler une journée par semaine sur
|
||
un projet qui me tiens vraiment à cœur: daybed
|
||
(<a href="http://daybed.rtfd.org">http://daybed.rtfd.org</a>). L&#8217;objectif est de faire en sorte que le
|
||
projet avance et soit utilisé au sein de&nbsp;mozilla.</p>
|
||
<p>Avant toute autre chose, il faudra faire des changements de &#8220;pitch&#8221; pour
|
||
qu&#8217;il soit plus simple d&#8217;expliquer ce que Daybed souhaite faire, mais…
|
||
c&#8217;est une autre&nbsp;histoire.</p></content><category term="journal"></category></entry><entry><title>Des carnets d’esquisse</title><link href="https://blog.notmyidea.org/des-carnets-desquisse.html" rel="alternate"></link><published>2013-08-16T00:00:00+02:00</published><updated>2013-08-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-08-16:/des-carnets-desquisse.html</id><summary type="html">
|
||
<p>Je me rends compte que je n&#8217;écris pas si souvent que ça ici,
|
||
principalement parce que je me sens obligé d&#8217;y écrire en Anglais, mais
|
||
aussi parce que je le considère comme un espace ou les choses doivent
|
||
êtres abouties et non pas&nbsp;expérimentales.</p>
|
||
<p>Des fois j&#8217;ai …</p></summary><content type="html">
|
||
<p>Je me rends compte que je n&#8217;écris pas si souvent que ça ici,
|
||
principalement parce que je me sens obligé d&#8217;y écrire en Anglais, mais
|
||
aussi parce que je le considère comme un espace ou les choses doivent
|
||
êtres abouties et non pas&nbsp;expérimentales.</p>
|
||
<p>Des fois j&#8217;ai cette envie d&#8217;ouvrir un &#8220;carnet&#8221; et d&#8217;y jeter juste
|
||
quelques notes. Pas grand chose: mes quelques pensées ou alors des liens
|
||
que je veux me garder de coté, des pensées que je souhaite partager… Un
|
||
endroit ou je peux venir écrire quelque chose et le compléter plus&nbsp;tard.</p>
|
||
<p>Du coup, le flux Atom contiens désormais quelques notes sur des sujets
|
||
variés. Ces notes ne sont pas relayées sur la page d&#8217;accueil, mais vous
|
||
pouvez les trouver dans <a href="/notes">la section notes</a>.</p>
|
||
<p>Je ne sais pas encore si il s&#8217;agit du meilleur endroit pour ça, mais peu
|
||
importe, essayons. A bas la pudeur&nbsp;rédactionelle.</p>
|
||
<p>J&#8217;ai du au passage chambouler un peu vos agrégateurs, pardonnez moi&nbsp;:)</p>
|
||
<h2 id="le-retour-des-commentaires">Le retour des&nbsp;commentaires</h2>
|
||
<p>Au passage, je ne me rappelle plus quand exactement, mais j&#8217;avais décidé
|
||
de supprimer les commentaires de cet espace. Paf, apu. Comme ça, sans&nbsp;prévenir.</p>
|
||
<p>Les raisons en étaient à la fois techniques (je ne souhaitait pas avoir
|
||
recours à disqus qui est un silo propriétaire de plus) et parce que je
|
||
considérais que les commentaires n&#8217;avaient que peu d&#8217;intérêt. Ceci dit,
|
||
le manque d&#8217;échange me manque; j&#8217;aimerais bien savoir ce que vous pensez
|
||
de ce que j&#8217;écris des fois, et avoir des débats si nos opinions&nbsp;divergent.</p>
|
||
<p>Et puis bon, partager dans un seul sens, c&#8217;est un peu dommage&nbsp;!</p>
|
||
<p>Il est maintenant possible, avec <a href="http://talka.tv">talka.tv</a> d&#8217;héberger
|
||
soi même ses commentaires. J&#8217;ai dans l&#8217;idée d&#8217;héberger une instance de
|
||
ce service sur discus.notmyidea.org, ou d&#8217;utiliser Daybed pour faire la
|
||
même chose, mais faut il encore que je le fasse, alors en attendant,
|
||
j&#8217;ai réactivé disqus ici! (Le mieux est l&#8217;ennemi du bien, paraît il&nbsp;!)</p></content><category term="journal"></category></entry><entry><title>François Elie : Quelle école pour la société de l’information ?</title><link href="https://blog.notmyidea.org/francois-elie-quelle-ecole-pour-la-societe-de-linformation.html" rel="alternate"></link><published>2013-06-14T00:00:00+02:00</published><updated>2013-06-14T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-06-14:/francois-elie-quelle-ecole-pour-la-societe-de-linformation.html</id><summary type="html">
|
||
<p><a href="http://www.framablog.org/index.php/post/2013/06/11/francois-elie-education-conference">http://www.framablog.org/index.php/post/2013/06/11/francois-elie-education-conference</a></p>
|
||
<p>Quelques bouts&nbsp;selectionnés.</p>
|
||
<blockquote>
|
||
<p>Mais pourquoi continue t-on à enseigner des maths à des gens qui ne
|
||
vont pas les utiliser ? Ben évidemment c’est parce qu’on n’est pas
|
||
dans une école de l’initiation où les mathématiciens …</p></blockquote></summary><content type="html">
|
||
<p><a href="http://www.framablog.org/index.php/post/2013/06/11/francois-elie-education-conference">http://www.framablog.org/index.php/post/2013/06/11/francois-elie-education-conference</a></p>
|
||
<p>Quelques bouts&nbsp;selectionnés.</p>
|
||
<blockquote>
|
||
<p>Mais pourquoi continue t-on à enseigner des maths à des gens qui ne
|
||
vont pas les utiliser ? Ben évidemment c’est parce qu’on n’est pas
|
||
dans une école de l’initiation où les mathématiciens font ça entre eux
|
||
et on n’est pas non plus dans une école de l’apprentissage où l’école
|
||
a pour but de donner un métier, un bagage utilisable. L’école ne sert
|
||
évidemment pas à ça. D’ailleurs heureusement parce que sinon on
|
||
n’enseignerait pas la philosophie qui ne sert à rien à part
|
||
fabriquer des profs de philosophie&nbsp;!</p>
|
||
<p>On n’a pas besoin de tableau numérique pour enseigner l’informatique
|
||
elle-même pour enseigner la science. De la même façon on n’a pas
|
||
besoin de machine à calculer pour enseigner les mathématiques.
|
||
Évidemment ! On n’a pas besoin d’une machine à calculer pour savoir
|
||
faire une division. Au contraire, surtout pas&nbsp;!</p>
|
||
<p>Il faut cesser d’opposer l’enseignement de la programmation d’une part
|
||
et l’enseignement des usages, c’est important mais ça c’est l’école
|
||
des maîtres et des esclaves. Ce qu’il faut enseigner, vite et à tous,
|
||
c’est la science, pas la technologie ou l’usage. C’est en amont de la
|
||
programmation, l’algorithmique. C’est, en amont de telle
|
||
instanciation, du codage, du chiffrement, la théorie, quelque chose
|
||
qui comme les maths n’ont besoin que d’une craie et d’un tableau&nbsp;noir.</p>
|
||
<p>Ce n&#8217;est pas un hasard si le mot &#8220;numérique&#8221; à remplaçé le mot
|
||
&#8220;informatique&#8221;, c&#8217;est qu&#8217;on voudrait nous faire croire qu&#8217;il n&#8217;y a pas
|
||
besoin de&nbsp;l&#8217;apprendre.</p>
|
||
</blockquote></content><category term="notes"></category></entry><entry><title>Notes: Économie libidinale et économie politique</title><link href="https://blog.notmyidea.org/notes-economie-libidinale-et-economie-politique.html" rel="alternate"></link><published>2013-06-07T00:00:00+02:00</published><updated>2013-06-07T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-06-07:/notes-economie-libidinale-et-economie-politique.html</id><summary type="html">
|
||
<p>Une enquete d&#8217;un cabinet de marketing american <span class="caps">ARI</span> qui pour la première
|
||
fois en 2004 disait qu&#8217;on voyait aparaitre des &#8220;alter consommateurs&#8221;,
|
||
qui n&#8217;étaient pas de gens qui consommaient moins, mais qui étaient des
|
||
gens malheureux de consommer. Et qui définissaient la consommation comme
|
||
une dépendance et …</p></summary><content type="html">
|
||
<p>Une enquete d&#8217;un cabinet de marketing american <span class="caps">ARI</span> qui pour la première
|
||
fois en 2004 disait qu&#8217;on voyait aparaitre des &#8220;alter consommateurs&#8221;,
|
||
qui n&#8217;étaient pas de gens qui consommaient moins, mais qui étaient des
|
||
gens malheureux de consommer. Et qui définissaient la consommation comme
|
||
une dépendance et une&nbsp;addiction.</p>
|
||
<p>Un autre comportement s&#8217;est développé: le modèle &#8220;collaboratif et
|
||
contributif&#8221;. Ce modèle ne se repose pas sur la consommation mais sur
|
||
l&#8217;implication et la collaboration. Ce modèle est induit par internet,
|
||
qui ne repose plus sur l&#8217;opposition production /&nbsp;consommation.</p>
|
||
<p>Sur internet nous ne sommes pas des simples consommateurs, puisque vous
|
||
êtes un expéditeur /&nbsp;distributeur.</p>
|
||
<p>Le changement prduit par internet est le fait que les gens ne sont plus
|
||
simplement des consommateurs,mais sont également producteurs de contenus
|
||
/ viennent améliorer les contenus&nbsp;existants.</p>
|
||
<p>Note perso: quid du culte de la personalité qui en ressort ? Ce qu&#8217;il
|
||
apelle l&#8217;écologie relationelle&nbsp;?</p>
|
||
<p>Quel est le manque que vient combler facebook par exemple ? Et quel est
|
||
l&#8217;impact que ces nouveaux réseaux ont sur les modèles relationels que
|
||
l&#8217;ont connait (famille, école, droit,&nbsp;etc.).</p>
|
||
<h2 id="citations">Citations</h2>
|
||
<blockquote>
|
||
<p>Une révolution c&#8217;est le fait de faire une boucle est d&#8217;arriver au
|
||
terme de quelque chose. D&#8217;avoir clôt un cycle. La lune fait des
|
||
révolutions&nbsp;aussi.</p>
|
||
<p>81% des Américains déclarent que le consumerisme est une plaie pour
|
||
l&#8217;amérique (d&#8217;après Juliet&nbsp;Score)</p>
|
||
</blockquote></content><category term="notes"></category></entry><entry><title>Le revenu de base</title><link href="https://blog.notmyidea.org/le-revenu-de-base.html" rel="alternate"></link><published>2013-03-10T00:00:00+01:00</published><updated>2013-03-10T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-03-10:/le-revenu-de-base.html</id><summary type="html">
|
||
<iframe width="560" height="315" src="http://www.youtube.com/embed/-cwdVDcm-Z0"
|
||
frameborder="0" allowfullscreen></iframe>
|
||
|
||
<p>Quelques notes prises en visualisant le documentaire &#8220;le revenu de&nbsp;base&#8221;.</p>
|
||
<ul>
|
||
<li>4 Allemands sur 10&nbsp;travaillent.</li>
|
||
<li>3/10 (les enfants et&nbsp;jeunes)</li>
|
||
<li>2/10 retraite /&nbsp;rente</li>
|
||
<li>1/10 assurance chomage / <span class="caps">AS</span></li>
|
||
<li>41% sont le fruit d&#8217;un travail&nbsp;rémunéré.</li>
|
||
</ul>
|
||
<p>Le revenu de base est&nbsp;inconditionnel.</p>
|
||
<p>Le marché du travail ne …</p></summary><content type="html">
|
||
<iframe width="560" height="315" src="http://www.youtube.com/embed/-cwdVDcm-Z0"
|
||
frameborder="0" allowfullscreen></iframe>
|
||
|
||
<p>Quelques notes prises en visualisant le documentaire &#8220;le revenu de&nbsp;base&#8221;.</p>
|
||
<ul>
|
||
<li>4 Allemands sur 10&nbsp;travaillent.</li>
|
||
<li>3/10 (les enfants et&nbsp;jeunes)</li>
|
||
<li>2/10 retraite /&nbsp;rente</li>
|
||
<li>1/10 assurance chomage / <span class="caps">AS</span></li>
|
||
<li>41% sont le fruit d&#8217;un travail&nbsp;rémunéré.</li>
|
||
</ul>
|
||
<p>Le revenu de base est&nbsp;inconditionnel.</p>
|
||
<p>Le marché du travail ne pourra pas suffire à toute la population. En
|
||
refusant l&#8217;idée du <span class="caps">RDB</span>, on est obligé de croire en la croissance&nbsp;économique.</p>
|
||
<p>Différence entre une approche qantitative du travail <span class="caps">VS</span> une approche&nbsp;sociale.</p>
|
||
<p>La croissance éco ≠ croissance de&nbsp;l&#8217;emploi.</p>
|
||
<p>Parallelle entre le <span class="caps">RDB</span> et la déclaration des droits de l&#8217;homme. &#8220;Et qui
|
||
voudra faire le sale boulot&nbsp;?&#8221;</p>
|
||
<p>Utopie veut dire le &#8220;non lieu&#8221;, le lieu qu&#8217;on à pas encore trouvé ici
|
||
sur terre, à part dans notre&nbsp;imaginaire.</p>
|
||
<p>Agriculture: Il y à 100 ans, qqn qui travaillait dans l&#8217;agriculture
|
||
produisait assez pour 3 autres personnes. ajd un agriculteur produit
|
||
assez pour 120 personnes, via des machines énormes et à la&nbsp;rationalisation.</p>
|
||
<p>Rationalisation: moins&nbsp;d&#8217;emploi.</p>
|
||
<p>La condition de pouvoir refuser un travail est très&nbsp;importante.</p>
|
||
<h2 id="citations">Citations</h2>
|
||
<blockquote>
|
||
<p>Le financmenet est acquis, la dificulté c&#8217;est la&nbsp;liberté</p>
|
||
<p>— <span class="caps">NA</span></p>
|
||
<p>Il faut en finir avec cette idée fausse, selon laquelle seul le
|
||
travail rémunéré constitue une contribution méritoire à la société, en
|
||
réalité, c&#8217;est souvent exactement&nbsp;l&#8217;inverse.</p>
|
||
<p>— Katja Kipping, membre du parlement&nbsp;allemand.</p>
|
||
<p>Si les gens on déjà une sécurité matérielle, ils sont plus difficiles
|
||
à&nbsp;corrompre.</p>
|
||
<p>— Katja&nbsp;Kipping</p>
|
||
<p>Soutenir les populations sans poser de condition. c&#8217;est un principe
|
||
qui à la longe, devra s&#8217;imposer. Mais il lui faudra d&#8217;abord affronter
|
||
les droits et privilèges dont on bénéficie&nbsp;aujourd&#8217;hui.</p>
|
||
<p>—&nbsp;Anonyme.</p>
|
||
<p>Si les revenus étaient uniquement lié au travail, il faudrait donner
|
||
les plus hauts revenus aux&nbsp;machines.</p>
|
||
</blockquote>
|
||
<p>Le sens de l&#8217;économie, c&#8217;est de libérer l&#8217;homme du travail Beaucoup de
|
||
gens qui ont une &#8220;place de travail&#8221;, n&#8217;ont en réalité qu&#8217;une &#8220;place de&nbsp;revenu&#8221;.</p>
|
||
<h2 id="chiffres">Chiffres</h2>
|
||
<p>Un sondage à été effectué. La question est: &#8220;Si vous aviez un revenu de
|
||
base, est-ce que vous iriez encore travailler&nbsp;?&#8221;</p>
|
||
<ul>
|
||
<li>\~60% disent&nbsp;oui</li>
|
||
<li>30% répondent oui, mais plus à plein&nbsp;temps.</li>
|
||
<li>10% pour faire autre&nbsp;chose.</li>
|
||
</ul>
|
||
<p>Avec une question&nbsp;différente:</p>
|
||
<p><span class="dquo">&#8220;</span>Si on instaurait un revenu de base, est-ce que vous pensez que les
|
||
autres iraient travailler&nbsp;?&#8221;</p>
|
||
<ul>
|
||
<li>\~80% répondent&nbsp;non.</li>
|
||
</ul>
|
||
<p>C&#8217;est un changement aussi dans les modes d&#8217;éducation, on nous enseigne à
|
||
être &#8220;employable&#8221;, et non pas à apprendre quelque chose qui nous
|
||
interesse. Les gens ont peur de ne pas trouver du&nbsp;travail.</p>
|
||
<h2 id="ressources">Ressources</h2>
|
||
<ul>
|
||
<li>Le sens commun, Thomas&nbsp;Payne.</li>
|
||
<li>Peter&nbsp;Ulrich</li>
|
||
</ul>
|
||
<h2 id="comment-financer-le-rdb">Comment financer le <span class="caps">RDB</span></h2>
|
||
<p>Si l’on se fie à son produit intérieur brut (<span class="caps">PIB</span>), la France est
|
||
aujourd’hui le cinquième pays le plus riche du monde. En 2010, le
|
||
revenu disponible (après versement des pres- tations sociales et
|
||
prélèvement des impôts directs) s’y élevait à 1 276 euros par mois et
|
||
par personne, adultes et enfants confondus. Nous disposons donc de
|
||
ressources suffisantes pour garantir à chaque individu 1 276 euros si
|
||
l’on décidait d’opérer un partage strictement égalitaire. C’est
|
||
nettement plus que le seuil de pauvreté actuel, fixé en France à 60 % du
|
||
revenu médian (1), soit 960 euros par adulte. Qui peut le plus pouvant
|
||
le moins, la France a donc sans nul doute les moyens d’assurer à tous
|
||
ses résidents un revenu au moins égal au seuil de&nbsp;pauvreté.</p>
|
||
<h2 id="a-reculons-par-andre-gorz">À Reculons, par André&nbsp;Gorz.</h2>
|
||
<p>(Paru dans le monde diplomatique de Juin&nbsp;1990)</p>
|
||
<p><em>Proche de Jean-Paul Sartre, cofondateur, en 1964, du Nouvel
|
||
Observateur, le philosophe André Gorz (1923-2007) s’est converti
|
||
progressivement à un écosocialisme dont il est devenu l’un des
|
||
principaux théoriciens. En 1990, dans nos colonnes, sous le titre «
|
||
Pourquoi la société salariale a besoin de nouveaux valets », il
|
||
formulait une critique de l’idéologie du travail qui devait l’amener
|
||
quelques années plus tard à se prononcer en faveur d’un revenu&nbsp;d’existence.</em></p>
|
||
<p>Dans l’ensemble des pays capitalistes d’Europe, on produit trois à
|
||
quatre fois plus de richesses qu’il y a trente-cinq ans ; cette
|
||
production n’exige pas trois fois plus d’heures de travail, mais une
|
||
quantité de travail beaucoup plus faible.&nbsp;(&#8230;)</p>
|
||
<p>Nous sortons de la civilisation du travail, mais nous en sortons à
|
||
reculons, et nous entrons à reculons dans une civilisation du temps
|
||
libéré, incapables de la voir et de la vouloir, incapables donc de
|
||
civiliser le temps libéré qui nous échoit, et de fonder une culture du
|
||
temps disponible et une culture des activités choisies pour relayer et
|
||
compléter les cultures techniciennes et profes- sionnelles qui dominent
|
||
la scène.&nbsp;(&#8230;)</p>
|
||
<p>Pour près de la moitié de la population active, l’idéologie du travail
|
||
est devenue une mauvaise farce ; l’identification au travail est
|
||
désormais impossible, car le système économique n’a pas besoin ou n’a
|
||
pas un besoin régulier de leur capacité de travail. La réalité que nous
|
||
masque l’exaltation de la « ressource humaine », c’est que l’emploi
|
||
stable, à plein temps, durant toute l’année et toute la vie active,
|
||
devient le privilège d’une minorité. Pour [les autres], le travail
|
||
cesse d’être un métier qui intègre dans une communauté productive et
|
||
définit une place dans la société. Ce que le patronat appelle «
|
||
flexibilité » se traduit pour les salariés par la précarité.&nbsp;(&#8230;)</p>
|
||
<p>Que doit être une société dans laquelle le travail à plein temps de tous
|
||
les citoyens n’est plus nécessaire, ni économiquement utile ? Quelles
|
||
priorités autres qu’économiques doit-elle se donner ? Comment doit-elle
|
||
s’y prendre pour que les gains de productivité, les économies de temps
|
||
de travail profitent à tout le monde ? Comment peut-elle redistribuer au
|
||
mieux tout le travail socialement utile de manière à ce que tout le
|
||
monde puisse travailler, mais travailler moins et mieux, tout en
|
||
recevant sa part des richesses socialement produites&nbsp;?</p>
|
||
<p>La tendance dominante est d’écarter ce genre de questions et de poser le
|
||
problème à l’envers : comment faire pour que, malgré les gains de
|
||
productivité, l’économie consomme autant de travail que par le passé ?
|
||
Comment faire pour que de nouvelles activités rémunérées viennent
|
||
occuper ce temps que, à l’échelle de la société, les gains de
|
||
productivité libèrent ? A quels nouveaux domaines d’activité peut-on
|
||
étendre les échanges marchands pour remplacer tant bien que mal les
|
||
emplois supprimés par ailleurs dans l’industrie et les services
|
||
industrialisés&nbsp;?</p>
|
||
<p>On connaît la réponse, pour laquelle les Etats-Unis et le Japon ont
|
||
montré la voie : le seul domaine dans lequel il est possible, en
|
||
économie libérale, de créer à l’avenir un grand nombre d’emplois, c’est
|
||
celui des services aux personnes. Le développement de l’emploi pourrait
|
||
être illimité si l’on parvenait à transformer en prestations de
|
||
services rétribuées les activités que les gens ont, jusqu’à présent,
|
||
assumées chacun pour soi. Les économistes parlent à ce sujet de «
|
||
nouvelle croissance plus riche en emplois », de « tertiarisation » de
|
||
l’économie, de « société de services » prenant le relais de la «
|
||
société industrielle » (1).&nbsp;(&#8230;)</p>
|
||
<p>Le problème de fond auquel nous sommes confrontés est celui d’un au-delà
|
||
de l’économie et, ce qui revient au même, d’un au- delà du travail
|
||
rémunéré. La rationalisation économique libère du temps, elle
|
||
continuera d’en libérer, et il n’est plus possible, par conséquent, de
|
||
faire dépendre le revenu des citoyens de la quantité de travail dont
|
||
l’économie a besoin. Il n’est plus possible, non plus, de continuer à
|
||
faire du travail rémunéré la source principale de l’identité et du sens
|
||
de la vie pour&nbsp;chacun.</p>
|
||
<p>La tâche d’une gauche, si gauche il doit y avoir, consiste à transformer
|
||
cette libération du temps en une liberté nouvelle et en des droits
|
||
nouveaux : le droit de chacun et de chacune de gagner sa vie en
|
||
travaillant, mais en travaillant de moins en moins, de mieux en mieux,
|
||
tout en recevant sa pleine part de la richesse socialement produite. Le
|
||
droit, d’autre part, de travailler de façon discontinue, intermittente,
|
||
sans perdre durant les intermittences de l’emploi le plein revenu – de
|
||
manière à ouvrir de nouveaux espaces aux activités sans but économique
|
||
et à reconnaître à ces activités qui n’ont pas la rémunération pour but
|
||
une dignité et une valeur éminentes, tant pour les individus que pour la
|
||
société&nbsp;elle-même.</p></content><category term="notes"></category></entry><entry><title>Des profils de confiance partout et pour tout ?</title><link href="https://blog.notmyidea.org/des-profils-de-confiance-partout-et-pour-tout.html" rel="alternate"></link><published>2013-02-04T00:00:00+01:00</published><updated>2013-02-04T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-02-04:/des-profils-de-confiance-partout-et-pour-tout.html</id><summary type="html">
|
||
<p>Depuis un petit moment déjà, le site covoiturage.fr est passé &#8220;payant&#8221;.
|
||
Il est désormais possible (et même obligatoire) de payer les trajets à l&#8217;avance, et en ligne, laissant au passage quelques royalties au site en&nbsp;question.</p>
|
||
<p>Précédemment, il était possible de retrouver le numéro des conducteur sur le …</p></summary><content type="html">
|
||
<p>Depuis un petit moment déjà, le site covoiturage.fr est passé &#8220;payant&#8221;.
|
||
Il est désormais possible (et même obligatoire) de payer les trajets à l&#8217;avance, et en ligne, laissant au passage quelques royalties au site en&nbsp;question.</p>
|
||
<p>Précédemment, il était possible de retrouver le numéro des conducteur sur le site et de les appeler soi même, chose maintenant&nbsp;automatisée.</p>
|
||
<p>Dès que cette décision à été prise, il y a eu des émules. Le site
|
||
<a href="http://covoiturage-libre.fr">Covoiturage Libre</a> à été d&#8217;ailleurs créé pour faire en sorte de garder &#8220;l&#8217;esprit&#8221; du covoiturage. Bref ça jasait dans les&nbsp;chaumières.</p>
|
||
<p>Il y à peu, j&#8217;ai reçu un <em>couriel</em> contenant un lien vers une vidéo d&#8217;<a href="http://www.covoiturage.fr/blog/2013-confiance">une conférence animée par le fondateur de
|
||
covoiturage.fr</a>.</p>
|
||
<p>Ils semblent vouloir parler de confiance, alors ça m&#8217;intrigue, d&#8217;autant que la présentation en question est donnée lors d&#8217;un évènement TEDx, auquel j&#8217;accorde un certain&nbsp;crédit.</p>
|
||
<h2 id="un-capital-de-confiance">Un &#8220;capital de&nbsp;confiance&#8221;</h2>
|
||
<p>Cette vidéo parle entre autres du <em>capital de confiance</em> que nous pouvons nous accorder les uns aux autres; et notamment du fait que ce capital de confiance n&#8217;est malheureusement pas partagé au dela d&#8217;un cercle de connaissances assez limité. Il reste dans notre cercle de connaissances proche, les amis des&nbsp;amis.</p>
|
||
<p>C&#8217;est donc une chose regrettable, parce que ça nous fait perdre du temps (et donc, <em>ohmygod</em> de l&#8217;argent) à tous pour construire cette confiance. Temps qui pourrait être mieux&nbsp;employé.</p>
|
||
<p>La solution proposée, attention les yeux, est de faire appel un maximum aux profils en ligne, une manière de &#8220;prouver au monde&#8221; que nous sommes des personnes de confiance. Selon les termes de la présentation, nous pourrions alors tous devenir des &#8220;super héros du trust&#8221;, des&nbsp;&#8220;trustman&#8221;.</p>
|
||
<p>Grâce à des profils en ligne ou monsieur et madame tout le monde pourraient aller voter et donner leur avis sur les personnes qu&#8217;ils ont&nbsp;rencontré.</p>
|
||
<h2 id="lavenement-du-paiement-en-ligne">L&#8217;avènement du paiement en&nbsp;ligne</h2>
|
||
<p>On nous dit maintenant que le paiement en ligne est une révolution, un moyen de tracer le fait qu&#8217;il y à effectivement eu une transaction entre deux personnes; et que donc il en deviendrait un outil pour vérifier que la confiance est bien légitime, et non pas créée de toute pièce sur le profil de la personne en&nbsp;question.</p>
|
||
<p>Plus exactement, ce qui est dit est que le paiement en ligne permet de justifier qu&#8217;il y a bien eu transaction entre deux personnes, et que donc les commentaires et &#8220;notations&#8221; effectuées sont donc&nbsp;légitimes.</p>
|
||
<h2 id="ce-nest-pas-un-probleme-de-confiance">Ce n&#8217;est pas un problème de confiance&nbsp;!</h2>
|
||
<p>Bien que j&#8217;arrive à suivre le raisonnement, il soulève certaines
|
||
questions&nbsp;:</p>
|
||
<p>Si j&#8217;accorde de la confiance à quelqu&#8217;un dans mon cercle de
|
||
connaissances, c&#8217;est justement parce qu&#8217;il fait partie de ce cercle de connaissances. Pas parce qu&#8217;une personne que je ne connait pas me dit qu&#8217;il s&#8217;agit d&#8217;une personne de confiance. En d&#8217;autres termes, <strong>pourquoi ne garderions nous pas ces relations privilégiées de personne à personne&nbsp;?</strong></p>
|
||
<p>Dans le cadre du covoiturage, j&#8217;arrive à comprendre le raisonnement du paiement <em>à l&#8217;avance</em>, pour avoir souvent entendu parler de désistements à la dernière minute de la part des voyageurs. Le paiement à l&#8217;avance permet d&#8217;éviter ce genre de&nbsp;désagréments.</p>
|
||
<p>Mais cela n&#8217;as rien à voir avec la confiance, il s&#8217;agit d&#8217;engagement de la part des deux&nbsp;parties.</p>
|
||
<p>Et c&#8217;est bien ce qui semble poser problème: lorsqu&#8217;on s&#8217;attend à
|
||
partager le prix d&#8217;un trajet avec quelqu&#8217;un, c&#8217;est bien d&#8217;avoir quelque chose qui nous y engage. J&#8217;aime beaucoup l&#8217;idée de payer une fois dans la voiture, de garder cette transaction manuelle; et de laisser peu de place au paiements en ligne dans cette histoire, mais je n&#8217;ai pas d&#8217;autre solution&nbsp;miracle.</p>
|
||
<p>En tout cas, la question n&#8217;est pas la question de savoir avec qui on embarque, mais bel et bien la question de l&#8217;engagement des deux&nbsp;parties.</p>
|
||
<p>Nous sommes malheureusement dans une société qui est dirigée par la peur. On à peur de se faire agresser par le gars qui tends le pouce sur le bord de la route, peur de se faire envoyer un produit qui ne fonctionne pas via Amazon,&nbsp;etc.</p>
|
||
<p>En poussant l&#8217;idée dans ses retranchements, j&#8217;aurais bientôt peur de mes voisins alors je ne leur parlerais plus, parce qu&#8217;ils n&#8217;ont pas leur profil disponible en ligne ou parce que quelqu&#8217;un à eu une mauvaise expérience avec eux&nbsp;?</p>
|
||
<p>Exposer des choses qui relèvent de ma vie privée en ligne de la sorte me pose des problèmes éthiques: d&#8217;abord parce que je ne veux pas juger les gens a priori, ensuite parce que l&#8217;expérience d&#8217;une personne n&#8217;est peut-être pas représentative, tout&nbsp;simplement.</p>
|
||
<p>Donc non, ce n&#8217;est pas un problème de confiance, il s&#8217;agit d&#8217;un problème d&#8217;engagement, dans le cadre du covoiturage, et les profils en ligne n&#8217;ont rien à faire la dedans. Le principe du paiement à l&#8217;avance me semble intéressant, mais il n&#8217;est à mon avis pas lié au profils en&nbsp;ligne.</p>
|
||
<p>La vidéo termine sur un &#8220;libérez la valeur de la confiance&#8221;. Oui, mais la libérer pour qui ? Quels sont les problèmes liés à cette confiance rendue nécessaire partout et pour tout ? Cela ne nous ferait-il pas évoluer uniquement dans des cercles fermés&nbsp;? </p>
|
||
<p>Quelle place laisser à l&#8217;inconnu, à la surprise&nbsp;?</p>
|
||
<p>Cette volonté de &#8220;confiance partout&#8221; semble découler tout droit des délires sécuritaires que l&#8217;on nous sert à toutes les sauces. Et
|
||
maintenant cela serait rendu accessible à tous grâce à &#8220;l&#8217;intelligence collective&#8221;; gommant au passage les différences de valeur; Préférant éviter de rencontrer les inconnus aux profils&nbsp;&#8220;légers&#8221;.</p>
|
||
<p>Je sais pas vous, mais elle me fait peur cette&nbsp;idée.</p></content><category term="journal"></category></entry><entry><title>Implementing CORS in Cornice</title><link href="https://blog.notmyidea.org/implementing-cors-in-cornice.html" rel="alternate"></link><published>2013-02-04T00:00:00+01:00</published><updated>2013-02-04T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-02-04:/implementing-cors-in-cornice.html</id><summary type="html">
|
||
<div class="note">
|
||
|
||
<div class="admonition-title">
|
||
|
||
Note
|
||
|
||
</div>
|
||
|
||
I&#8217;m cross-posting [on the mozilla services
|
||
weblog](https://blog.mozilla.org/services/). Since this is the first
|
||
time we&#8217;re doing that, I though it could be useful to point you there.
|
||
Check it out and expect more technical articles there in the future.
|
||
|
||
</div>
|
||
|
||
<p>For security reasons, it …</p></summary><content type="html">
|
||
<div class="note">
|
||
|
||
<div class="admonition-title">
|
||
|
||
Note
|
||
|
||
</div>
|
||
|
||
I&#8217;m cross-posting [on the mozilla services
|
||
weblog](https://blog.mozilla.org/services/). Since this is the first
|
||
time we&#8217;re doing that, I though it could be useful to point you there.
|
||
Check it out and expect more technical articles there in the future.
|
||
|
||
</div>
|
||
|
||
<p>For security reasons, it&#8217;s not possible to do cross-domain requests. In
|
||
other words, if you have a page served from the domain lolnet.org, it
|
||
will not be possible for it to get data from&nbsp;notmyidea.org.</p>
|
||
<p>Well, it&#8217;s possible, using tricks and techniques like
|
||
<a href="http://en.wikipedia.org/wiki/JSONP"><span class="caps">JSONP</span></a>, but that doesn&#8217;t work all
|
||
the time (see <a href="#how-this-is-different-from-jsonp">the section below</a>). I
|
||
remember myself doing some simple proxies on my domain server to be able
|
||
to query other&#8217;s <span class="caps">API</span>.</p>
|
||
<p>Thankfully, there is a nicer way to do this, namely, &#8220;Cross Origin
|
||
Resource-Sharing&#8221;, or <a href="http://www.w3.org/TR/cors/"><span class="caps">CORS</span></a>.</p>
|
||
<h2 id="you-want-an-icecream-go-ask-your-dad-first">You want an icecream? Go ask your dad&nbsp;first.</h2>
|
||
<p>If you want to use <span class="caps">CORS</span>, you need the <span class="caps">API</span> you&#8217;re querying to support it;
|
||
on the server&nbsp;side.</p>
|
||
<p>The <span class="caps">HTTP</span> server need to answer to the <span class="caps">OPTIONS</span> verb, and with the
|
||
appropriate response&nbsp;headers.</p>
|
||
<p><span class="caps">OPTIONS</span> is sent as what the authors of the spec call a &#8220;preflight
|
||
request&#8221;; just before doing a request to the <span class="caps">API</span>, the <em>User-Agent</em> (the
|
||
browser most of the time) asks the permission to the resource, with an
|
||
<span class="caps">OPTIONS</span>&nbsp;call.</p>
|
||
<p>The server answers, and tell what is available and what&nbsp;isn&#8217;t:</p>
|
||
<p><img alt="The CORS flow (from the HTML5 CORS tutorial)" src="/images/cors_flow.png"></p>
|
||
<ul>
|
||
<li>
|
||
<p>1a. The User-Agent, rather than doing the call directly, asks the
|
||
server, the <span class="caps">API</span>, the permission to do the request. It does so with
|
||
the following&nbsp;headers:</p>
|
||
<ul>
|
||
<li><strong>Access-Control-Request-Headers</strong>, contains the headers the
|
||
User-Agent want to&nbsp;access.</li>
|
||
<li><strong>Access-Control-Request-Method</strong> contains the method the
|
||
User-Agent want to&nbsp;access.</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<p>1b. The <span class="caps">API</span> answers what is&nbsp;authorized:</p>
|
||
<ul>
|
||
<li><strong>Access-Control-Allow-Origin</strong> the origin that&#8217;s accepted. Can
|
||
be * or the domain&nbsp;name.</li>
|
||
<li><strong>Access-Control-Allow-Methods</strong> a <em>list</em> of allowed methods.
|
||
This can be cached. Note than the request asks permission for
|
||
one method and the server should return a list of accepted&nbsp;methods.</li>
|
||
<li><strong>Access-Allow-Headers</strong> a list of allowed headers, for all of
|
||
the methods, since this can be cached as&nbsp;well.</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<ol>
|
||
<li>The User-Agent can do the &#8220;normal&#8221;&nbsp;request.</li>
|
||
</ol>
|
||
</li>
|
||
</ul>
|
||
<p>So, if you want to access the /icecream resource, and do a <span class="caps">PUT</span> there,
|
||
you&#8217;ll have the following&nbsp;flow:</p>
|
||
<div class="highlight"><pre><span></span><code>&gt; OPTIONS /icecream
|
||
&gt; Access-Control-Request-Methods = PUT
|
||
&gt; Origin: notmyidea.org
|
||
&lt; Access-Control-Allow-Origin = notmyidea.org
|
||
&lt; Access-Control-Allow-Methods = PUT,GET,DELETE
|
||
200 OK
|
||
</code></pre></div>
|
||
|
||
<p>You can see that we have an Origin Header in the request, as well as a
|
||
Access-Control-Request-Methods. We&#8217;re here asking if we have the right,
|
||
as notmyidea.org, to do a <span class="caps">PUT</span> request on&nbsp;/icecream.</p>
|
||
<p>And the server tells us that we can do that, as well as <span class="caps">GET</span> and <span class="caps">DELETE</span>.</p>
|
||
<p>I&#8217;ll not cover all the details of the <span class="caps">CORS</span> specification here, but bear
|
||
in mind than with <span class="caps">CORS</span>, you can control what are the authorized methods,
|
||
headers, origins, and if the client is allowed to send authentication
|
||
information or&nbsp;not.</p>
|
||
<h2 id="a-word-about-security">A word about&nbsp;security</h2>
|
||
<p><span class="caps">CORS</span> is not an answer for every cross-domain call you want to do,
|
||
because you need to control the service you want to call. For instance,
|
||
if you want to build a feed reader and access the feeds on different
|
||
domains, you can be pretty much sure that the servers will not implement
|
||
<span class="caps">CORS</span>, so you&#8217;ll need to write a proxy yourself, to provide&nbsp;this.</p>
|
||
<p>Secondly, if misunderstood, <span class="caps">CORS</span> can be insecure, and cause problems.
|
||
Because the rules apply when a client wants to do a request to a server,
|
||
you need to be extra careful about who you&#8217;re&nbsp;authorizing.</p>
|
||
<p>An incorrectly secured <span class="caps">CORS</span> server can be accessed by a malicious client
|
||
very easily, bypassing network security. For instance, if you host a
|
||
server on an intranet that is only available from behind a <span class="caps">VPN</span> but
|
||
accepts every cross-origin call. A bad guy can inject javascript into
|
||
the browser of a user who has access to your protected server and make
|
||
calls to your service, which is probably not what you&nbsp;want.</p>
|
||
<h2 id="how-this-is-different-from-jsonp">How this is different from <span class="caps">JSONP</span>?</h2>
|
||
<p>You may know the <a href="http://en.wikipedia.org/wiki/JSONP"><span class="caps">JSONP</span></a> protocol.
|
||
<span class="caps">JSONP</span> allows cross origin, but for a particular use case, and does have
|
||
some drawbacks (for instance, it&#8217;s not possible to do DELETEs or PUTs
|
||
with <span class="caps">JSONP</span>).</p>
|
||
<p><span class="caps">JSONP</span> exploits the fact that it is possible to get information from
|
||
another domain when you are asking for javascript code, using the
|
||
\&lt;script&gt;&nbsp;element.</p>
|
||
<blockquote>
|
||
<p>Exploiting the open policy for \&lt;script&gt; elements, some pages use
|
||
them to retrieve JavaScript code that operates on dynamically
|
||
generated <span class="caps">JSON</span>-formatted data from other origins. This usage pattern
|
||
is known as <span class="caps">JSONP</span>. Requests for <span class="caps">JSONP</span> retrieve not <span class="caps">JSON</span>, but arbitrary
|
||
JavaScript code. They are evaluated by the JavaScript interpreter, not
|
||
parsed by a <span class="caps">JSON</span>&nbsp;parser.</p>
|
||
</blockquote>
|
||
<h2 id="using-cors-in-cornice">Using <span class="caps">CORS</span> in&nbsp;Cornice</h2>
|
||
<p>Okay, things are hopefully clearer about <span class="caps">CORS</span>, let&#8217;s see how we
|
||
implemented it on the&nbsp;server-side.</p>
|
||
<p>Cornice is a toolkit that lets you define resources in python and takes
|
||
care of the heavy lifting for you, so I wanted it to take care of the
|
||
<span class="caps">CORS</span> support as&nbsp;well.</p>
|
||
<p>In Cornice, you define a service like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">cornice</span> <span class="kn">import</span> <span class="n">Service</span>
|
||
|
||
<span class="n">foobar</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;foobar&quot;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s2">&quot;/foobar&quot;</span><span class="p">)</span>
|
||
|
||
<span class="c1"># and then you do something with it</span>
|
||
<span class="nd">@foobar</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>
|
||
<span class="k">def</span> <span class="nf">get_foobar</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="c1"># do something with the request.</span>
|
||
</code></pre></div>
|
||
|
||
<p>To add <span class="caps">CORS</span> support to this resource, you can go this way, with the
|
||
cors_origins&nbsp;parameter:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">foobar</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;foobar&#39;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s1">&#39;/foobar&#39;</span><span class="p">,</span> <span class="n">cors_origins</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;*&#39;</span><span class="p">,))</span>
|
||
</code></pre></div>
|
||
|
||
<p>Ta-da! You have enabled <span class="caps">CORS</span> for your service. <strong>Be aware that you&#8217;re
|
||
authorizing anyone to query your server, that may not be what you&nbsp;want.</strong></p>
|
||
<p>Of course, you can specify a list of origins you trust, and you don&#8217;t
|
||
need to stick with *, which means &#8220;authorize&nbsp;everyone&#8221;.</p>
|
||
<h3 id="headers">Headers</h3>
|
||
<p>You can define the headers you want to expose for the&nbsp;service:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">foobar</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;foobar&#39;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s1">&#39;/foobar&#39;</span><span class="p">,</span> <span class="n">cors_origins</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;*&#39;</span><span class="p">,))</span>
|
||
|
||
<span class="nd">@foobar</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cors_headers</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;X-My-Header&#39;</span><span class="p">,</span> <span class="s1">&#39;Content-Type&#39;</span><span class="p">))</span>
|
||
<span class="k">def</span> <span class="nf">get_foobars_please</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="s2">&quot;some foobar for you&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<p>I&#8217;ve done some testing and it wasn&#8217;t working on Chrome because I wasn&#8217;t
|
||
handling the headers the right way (The missing one was Content-Type,
|
||
that Chrome was asking for). With my first version of the
|
||
implementation, I needed the service implementers to explicitely list
|
||
all the headers that should be exposed. While this improves security, it
|
||
can be frustrating while&nbsp;developing.</p>
|
||
<p>So I introduced an expose_all_headers flag, which is set to True by
|
||
default, if the service supports <span class="caps">CORS</span>.</p>
|
||
<h3 id="cookies-credentials">Cookies /&nbsp;Credentials</h3>
|
||
<p>By default, the requests you do to your <span class="caps">API</span> endpoint don&#8217;t include the
|
||
credential information for security reasons. If you really want to do
|
||
that, you need to enable it using the cors_credentials parameter. You
|
||
can activate this one on a per-service basis or on a per-method&nbsp;basis.</p>
|
||
<h3 id="caching">Caching</h3>
|
||
<p>When you do a preflight request, the information returned by the server
|
||
can be cached by the User-Agent so that it&#8217;s not redone before each
|
||
actual&nbsp;call.</p>
|
||
<p>The caching period is defined by the server, using the
|
||
Access-Control-Max-Age header. You can configure this timing using the
|
||
cors_max_age&nbsp;parameter.</p>
|
||
<h3 id="simplifying-the-api">Simplifying the <span class="caps">API</span></h3>
|
||
<p>We have cors_headers, cors_enabled, cors_origins, cors_credentials,
|
||
cors_max_age, cors_expose_all_headers … a fair number of
|
||
parameters. If you want to have a specific <span class="caps">CORS</span>-policy for your
|
||
services, that can be a bit tedious to pass these to your services all
|
||
the&nbsp;time.</p>
|
||
<p>I introduced another way to pass the <span class="caps">CORS</span> policy, so you can do
|
||
something like&nbsp;that:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">policy</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">enabled</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
||
<span class="n">headers</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;X-My-Header&#39;</span><span class="p">,</span> <span class="s1">&#39;Content-Type&#39;</span><span class="p">),</span>
|
||
<span class="n">origins</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;*.notmyidea.org&#39;</span><span class="p">),</span>
|
||
<span class="n">credentials</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
||
<span class="n">max_age</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
|
||
|
||
<span class="n">foobar</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;foobar&#39;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s1">&#39;/foobar&#39;</span><span class="p">,</span> <span class="n">cors_policy</span><span class="o">=</span><span class="n">policy</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="comparison-with-other-implementations">Comparison with other&nbsp;implementations</h2>
|
||
<p>I was curious to have a look at other implementations of <span class="caps">CORS</span>, in django
|
||
for instance, and I found <a href="https://gist.github.com/426829.js">a gist about
|
||
it</a>.</p>
|
||
<p>Basically, this adds a middleware that adds the &#8220;rights&#8221; headers to the
|
||
answer, depending on the&nbsp;request.</p>
|
||
<p>While this approach works, it&#8217;s not implementing the specification
|
||
completely. You need to add support for all the resources at&nbsp;once.</p>
|
||
<p>We can think about a nice way to implement this specifying a definition
|
||
of what&#8217;s supposed to be exposed via <span class="caps">CORS</span> and what shouldn&#8217;t directly in
|
||
your settings. In my opinion, <span class="caps">CORS</span> support should be handled at the
|
||
service definition level, except for the list of authorized hosts.
|
||
Otherwise, you don&#8217;t know exactly what&#8217;s going on when you look at the
|
||
definition of the&nbsp;service.</p>
|
||
<h2 id="resources">Resources</h2>
|
||
<p>There are a number of good resources that can be useful to you if you
|
||
want to either understand how <span class="caps">CORS</span> works, or if you want to implement it&nbsp;yourself.</p>
|
||
<ul>
|
||
<li><a href="http://enable-cors.org/">http://enable-cors.org/</a> is useful to get started when you don&#8217;t
|
||
know anything about <span class="caps">CORS</span>.</li>
|
||
<li>There is a <span class="caps">W3C</span> wiki page containing information that may be useful
|
||
about clients, common pitfalls etc:
|
||
<a href="http://www.w3.org/wiki/CORS_Enabled">http://www.w3.org/wiki/CORS_Enabled</a></li>
|
||
<li><em><span class="caps">HTML5</span> rocks</em> has a tutorial explaining how to implement <span class="caps">CORS</span>, with
|
||
<a href="http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server">a nice section about the
|
||
server-side</a>.</li>
|
||
<li>Be sure to have a look at the <a href="http://caniuse.com/#search=cors">clients support-matrix for this
|
||
feature</a>.</li>
|
||
<li>About security, <a href="https://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity">check out this&nbsp;page</a></li>
|
||
<li>If you want to have a look at the implementation code, check <a href="https://github.com/mozilla-services/cornice/pull/98/files">on&nbsp;github</a></li>
|
||
</ul>
|
||
<p>Of course, the <span class="caps">W3C</span> specification is the best resource to rely on. This
|
||
specification isn&#8217;t hard to read, so you may want to go through it.
|
||
Especially the <a href="http://www.w3.org/TR/cors/#resource-processing-model">&#8220;resource processing model&#8221;&nbsp;section</a></p></content><category term="code"></category></entry><entry><title>New year python meme, 2012</title><link href="https://blog.notmyidea.org/new-year-python-meme-2012.html" rel="alternate"></link><published>2013-01-07T00:00:00+01:00</published><updated>2013-01-07T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2013-01-07:/new-year-python-meme-2012.html</id><summary type="html">
|
||
<p>This series, also known as &#8220;<a href="http://ziade.org">Tarek Ziadé</a> strikes
|
||
again&#8221;, is a good occasion to take a look back at 2012 and see what I&#8217;ve
|
||
done related to python. So, let&#8217;s&nbsp;try.</p>
|
||
<p><strong>1. What’s the coolest Python application, framework or library you
|
||
have discovered in 2012&nbsp;?</strong></p>
|
||
<p>I discovered …</p></summary><content type="html">
|
||
<p>This series, also known as &#8220;<a href="http://ziade.org">Tarek Ziadé</a> strikes
|
||
again&#8221;, is a good occasion to take a look back at 2012 and see what I&#8217;ve
|
||
done related to python. So, let&#8217;s&nbsp;try.</p>
|
||
<p><strong>1. What’s the coolest Python application, framework or library you
|
||
have discovered in 2012&nbsp;?</strong></p>
|
||
<p>I discovered
|
||
<a href="http://docs.pylonsproject.org/en/latest/docs/pyramid.html">Pyramid</a>
|
||
this year and quite enjoyed it. I like the way they bring back some nice
|
||
concepts on the table, and how they compete with other frameworks.
|
||
That&#8217;s nicely decomposed and everything fits together really well. I
|
||
learned a bit about its internal routing mechanism when working on
|
||
<a href="http://cornice.rtfd.org">Cornice</a>, and it&#8217;s really well&nbsp;done.</p>
|
||
<p><strong>2. What new programming technique did you learn in 2012&nbsp;?</strong></p>
|
||
<p>I learned about asynchronous programming, something I wasn&#8217;t really
|
||
aware of. (Yes, that&#8217;s a shame). This was really helpful to understand
|
||
some bits of <a href="http://circus.io">Circus</a>. I also started to learn about
|
||
some related concepts present in <a href="http://golang.org">go</a> or in
|
||
<a href="http://erlang.org">erlang</a> with <a href="http://en.wikipedia.org/wiki/Actor_model">the actor&nbsp;model</a></p>
|
||
<p><strong>3. Which open source project did you contribute to the most in 2012 ?
|
||
What did you do&nbsp;?</strong></p>
|
||
<p>I worked a bunch on <a href="http://cornice.rtfd.org">Cornice</a> and
|
||
<a href="http://circus.io">Circus</a>, not as much as I would like, but that was
|
||
two really interesting projects. For Cornice, I completely <a href="http://blog.notmyidea.org/refactoring-cornice.html">refactored
|
||
the internals</a> back
|
||
in May, and since that, I added support for
|
||
<a href="https://github.com/SPORE/specifications"><span class="caps">SPORE</span></a> and am currently
|
||
working on porting it to Python 3 and adding support for
|
||
<a href="http://www.w3.org/TR/cors/"><span class="caps">CORS</span></a>. For Circus, I worked on the web
|
||
interface and on other bits of the projects related to&nbsp;stats.</p>
|
||
<p>I didn&#8217;t contributed that much to <a href="http://getpelican.com">Pelican</a>,
|
||
mainly because I&#8217;m less excited about it than I was previously: the
|
||
project is working and needs to focus more on code quality than
|
||
features. We started in this direction, hopefully it will pay-off; but I
|
||
committed a lot less code than&nbsp;previously.</p>
|
||
<p><strong>4. Which Python blog or website did you read the most in 2012&nbsp;?</strong></p>
|
||
<p>I really don&#8217;t know. I found some interesting python-related news on
|
||
<a href="http://news.ycombinator.com/">hacker news</a> and on the printed version
|
||
as well, <a href="http://hackermonthly.com/">hacker monthly</a>. Twitter and <span class="caps">IRC</span>
|
||
got me some interesting articles as&nbsp;well.</p>
|
||
<p><strong>5. What are the three top things you want to learn in 2013&nbsp;?</strong></p>
|
||
<p>On the computer science side, I want to learn more about other
|
||
paradigms, maybe in other languages. I like python, but I want to learn
|
||
about other concepts, maybe some of them don&#8217;t really fit with&nbsp;python.</p>
|
||
<p>For instance, I don&#8217;t know that much about pattern matching or about the
|
||
actor model. Well I know what it is, but I would like to make good use
|
||
of them in order to have something nice and&nbsp;useful.</p>
|
||
<p>Also, I want to learn how to make a product. From scratch. Which means
|
||
designing, implementing and maintaining something. Maybe this will be
|
||
the case with <a href="https://github.com/spiral-project/daybed">daybed</a> ? Who&nbsp;knows.</p>
|
||
<p>I want to get better at building communities. Working with others is
|
||
something that can be complex and quite hard sometimes. I want to learn
|
||
how to handle this&nbsp;better.</p>
|
||
<p>On the other side, I want to learn about tons of other non-tech things:
|
||
taking pictures, finding a good balance between life and work, working
|
||
with children, teaching and animating workshops, writing articles, be
|
||
better at reading (being critic when I&#8217;m&nbsp;thinking!).</p>
|
||
<p><strong>6. What is the top software, application or library you wish someone
|
||
would write in 2013&nbsp;?</strong></p>
|
||
<p>The one missing thing, <span class="caps">IMO</span>, is a <strong>good</strong> webmail reader, in python. One
|
||
we could contribute to, one we could write features for, and one that
|
||
could come and compete with gmail, in term of features of <span class="caps">UI</span>.</p>
|
||
<p>However, most of the time, I&#8217;m just impressed by the new ideas that come
|
||
from others. I would like to have a library to handle the actor model in
|
||
a nice way in Python, I would like to see packaging fixed in python&nbsp;:-)</p>
|
||
<p>Want to do your own list? Here&#8217;s&nbsp;how:</p>
|
||
<ul>
|
||
<li>copy-paste the questions and answer to them in your&nbsp;blog</li>
|
||
<li>tweet it with the #2012pythonmeme&nbsp;hashtag</li>
|
||
</ul></content><category term="journal"></category></entry><entry><title>Status board</title><link href="https://blog.notmyidea.org/status-board.html" rel="alternate"></link><published>2012-12-29T00:00:00+01:00</published><updated>2012-12-29T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-29:/status-board.html</id><summary type="html">
|
||
<p>À force de démarrer des services web pour un oui et pour un non, de
|
||
proposer à des copains d&#8217;héberger leurs sites, de faire pareil pour
|
||
quelques assos etc, je me suis retrouvé avec, comme dirait l&#8217;autre, <em>une
|
||
bonne platrée</em> de sites et de services à gérer sur …</p></summary><content type="html">
|
||
<p>À force de démarrer des services web pour un oui et pour un non, de
|
||
proposer à des copains d&#8217;héberger leurs sites, de faire pareil pour
|
||
quelques assos etc, je me suis retrouvé avec, comme dirait l&#8217;autre, <em>une
|
||
bonne platrée</em> de sites et de services à gérer sur lolnet.org, mon&nbsp;serveur.</p>
|
||
<p>Jusqu&#8217;à très récemment, rien de tout ça n&#8217;était sauvegardé, et non plus
|
||
monitoré. Après quelques recherches, je suis tombé sur
|
||
<a href="http://www.stashboard.org/">stashboard</a>, un &#8220;status board&#8221; qu&#8217;il est
|
||
bien fait. Le seul problème, c&#8217;est écrit pour se lancer sur <span class="caps">GAE</span>, <em>Google
|
||
App Engine</em>. Heureusement, c&#8217;est open-source, et ça a été forké pour
|
||
donner naissance à
|
||
<a href="https://github.com/bfirsh/whiskerboard">whiskerboard</a> (la planche
|
||
moustachue, pour les non&nbsp;anglophones).</p>
|
||
<p><img alt="Capture d'écran du site." src="/images/status_board.png"></p>
|
||
<h2 id="verifier-le-statut-des-services">Vérifier le statut des&nbsp;services</h2>
|
||
<p>Donc, c&#8217;est chouette, c&#8217;est facile à installer, tout ça, mais… mais ça ne fait en fait pas ce que je veux: ça ne fait que m&#8217;afficher le statut des services, mais ça ne vérifie pas que tout est bien&nbsp;&#8220;up&#8221;.</p>
|
||
<p>Bon, un peu embêtant pour moi, parce que c&#8217;est vraiment ça que je voulais. Pas grave, je sais un peu coder, autant que ça serve. J&#8217;ai ajouté quelques fonctionnalités au soft, qui sont disponibles sur mon fork, sur github:: <a href="https://github.com/almet/whiskerboard">https://github.com/almet/whiskerboard</a>&nbsp;.</p>
|
||
<p>Entres autres, il est désormais possible de lancer
|
||
<a href="http://celeryproject.org/">celery</a> en tache de fond et de vérifier périodiquement que les services sont toujours bien vivants, en utilisant une tache&nbsp;spécifique.</p>
|
||
<p>C&#8217;était un bonheur de développer ça (on a fait ça à deux, avec guillaume, avec un mumble + tmux en pair prog, en une petite soirée, ça&nbsp;dépote).</p>
|
||
<p>Les modifications sont assez simples, vous pouvez aller jeter un œil aux changements ici:
|
||
<a href="https://github.com/almet/whiskerboard/compare/b539337416...master">https://github.com/almet/whiskerboard/compare/b539337416&#8230;master</a></p>
|
||
<p>En&nbsp;gros:</p>
|
||
<ul>
|
||
<li>ajout d&#8217;une connection_string aux services (de la forme&nbsp;protocol://host:port)</li>
|
||
<li>ajout d&#8217;une commande check_status qui s&#8217;occupe d&#8217;itérer sur les
|
||
services et de lancer des taches celery qui vont bien, en fonction
|
||
du&nbsp;protocole</li>
|
||
<li>ajout des taches en&nbsp;question</li>
|
||
</ul>
|
||
<h2 id="deploiement">Déploiement</h2>
|
||
<p>Le plus long a été de le déployer en fin de compte, parce que je ne
|
||
voulais pas déployer mon service de supervision sur mon serveur,&nbsp;forcément.</p>
|
||
<p>Après un essai (plutôt rapide en fait) sur <a href="http://heroku.com">heroku</a>,
|
||
je me suis rendu compte qu&#8217;il me fallait payer pas loin de 35$ par mois
|
||
pour avoir un process celeryd qui tourne, donc j&#8217;ai un peu cherché
|
||
ailleurs, pour finalement déployer la chose chez
|
||
<a href="https://www.alwaysdata.com/">alwaysdata</a></p>
|
||
<p>Après quelques péripéties, j&#8217;ai réussi à faire tourner le tout, ça à été
|
||
un peu la bataille au départ pour installer virtualenv (j&#8217;ai du faire
|
||
des changements dans mon <span class="caps">PATH</span> pour que ça puisse marcher), voici mon&nbsp;`.bash_profile`:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">export</span><span class="w"> </span><span class="n">PYTHONPATH</span><span class="o">=~/</span><span class="n">modules</span><span class="o">/</span>
|
||
<span class="k">export</span><span class="w"> </span><span class="n">PATH</span><span class="o">=$</span><span class="n">HOME</span><span class="o">/</span><span class="n">modules</span><span class="o">/</span><span class="n">bin</span><span class="p">:</span><span class="o">$</span><span class="n">HOME</span><span class="o">/</span><span class="n">modules</span><span class="o">/</span><span class="p">:</span><span class="o">$</span><span class="n">PATH</span>
|
||
</code></pre></div>
|
||
|
||
<p>Et après y&#8217;a plus qu&#8217;à installer avec&nbsp;`easy_install`:</p>
|
||
<div class="highlight"><pre><span></span><code>easy_install --install-dir ~/modules -U pip
|
||
easy_install --install-dir ~/modules -U virtualenv
|
||
</code></pre></div>
|
||
|
||
<p>Et à créer le&nbsp;virtualenv:</p>
|
||
<div class="highlight"><pre><span></span><code>virtualenv venv
|
||
venv/bin/pip install -r requirements.txt
|
||
</code></pre></div>
|
||
|
||
<p>Dernière étape, la création d&#8217;un fichier application.wsgi qui s&#8217;occupe
|
||
de rendre l&#8217;application disponible, avec le bon&nbsp;venv:</p>
|
||
<h2 id="ssl-et-requests"><span class="caps">SSL</span> et&nbsp;Requests</h2>
|
||
<p>Quelques tours de manivelle plus loin, j&#8217;ai un celeryd qui tourne et qui
|
||
consomme les taches qui lui sont envoyées (pour des questions de
|
||
simplicité, j&#8217;ai utilisé le backend django de celery, donc pas besoin
|
||
d&#8217;<span class="caps">AMQP</span>, par&nbsp;exemple).</p>
|
||
<p>Problème, les ressources que je vérifie en <span class="caps">SSL</span> (<span class="caps">HTTPS</span>) me jettent. Je
|
||
sais pas exactement pourquoi à l&#8217;heure qu&#8217;il est, mais il semble que
|
||
lorsque je fais une requête avec
|
||
<a href="http://docs.python-requests.org/en/latest/">Requests</a> je me récupère
|
||
des <em>Connection Refused</em>. Peut être une sombre histoire de proxy ? En
|
||
attendant, les appels avec <span class="caps">CURL</span> fonctionnent, donc j&#8217;ai fait <a href="https://github.com/ametaireau/whiskerboard/blob/master/board/tasks.py#L17">un
|
||
fallback vers <span class="caps">CURL</span> lorsque les autres méthodes
|
||
échouent</a>.
|
||
Pas super propre, mais ça&nbsp;fonctionne.</p>
|
||
<p><strong><span class="caps">EDIT</span></strong> Finalement, il se trouve que mon serveur était mal configuré.
|
||
J&#8217;utilisais haproxy + stunnel, et la négiciation <span class="caps">SSL</span> se passait mal. Une
|
||
fois <span class="caps">SSL</span> et <span class="caps">TLS</span> activés, et SSLv2 désactivé, tout fonctionne&nbsp;mieux.</p>
|
||
<h2 id="et-voila">Et&nbsp;voilà</h2>
|
||
<p>Finalement, j&#8217;ai mon joli status-board qui tourne à merveille sur
|
||
<a href="http://status.lolnet.org">http://status.lolnet.org</a>&nbsp;:-)</p></content><category term="code"></category></entry><entry><title>Habitat collectif</title><link href="https://blog.notmyidea.org/habitat-collectif.html" rel="alternate"></link><published>2012-12-28T00:00:00+01:00</published><updated>2012-12-28T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-28:/habitat-collectif.html</id><summary type="html">
|
||
<p>Habiter à plusieurs, partager un lieu de vie, monter une communauté,
|
||
changer nos modes de vie et prendre plus de temps les uns pour les&nbsp;autres.</p>
|
||
<p>Ça fait réfléchir un peu quand même, non ? en tout cas ça marche chez&nbsp;moi.</p>
|
||
<p>Voilà quelques ressources qui peuvent être utiles si jamais …</p></summary><content type="html">
|
||
<p>Habiter à plusieurs, partager un lieu de vie, monter une communauté,
|
||
changer nos modes de vie et prendre plus de temps les uns pour les&nbsp;autres.</p>
|
||
<p>Ça fait réfléchir un peu quand même, non ? en tout cas ça marche chez&nbsp;moi.</p>
|
||
<p>Voilà quelques ressources qui peuvent être utiles si jamais vous aussi
|
||
ça vous&nbsp;titille:</p>
|
||
<ul>
|
||
<li><a href="http://www.habicoop.fr/IMG/pdf/Memoire_hbtat_coop_Vaulx-2.pdf">L’Habitat Coopératif : Solution au problème de responsabilisation
|
||
sociale des copropriétaires sur la commune de Vaulx en Velin
|
||
?</a> -
|
||
mémoire <span class="caps">REPIQUET</span> Anne&nbsp;2005.</li>
|
||
<li>Un bouquin à lire avec plein d&#8217;infos: <a href="http://www.ecosociete.org/t101.php">Vivre
|
||
autrement</a> de Diana Leafe&nbsp;Christian.</li>
|
||
<li>…</li>
|
||
</ul></content><category term="notes"></category></entry><entry><title>Tricot</title><link href="https://blog.notmyidea.org/tricot.html" rel="alternate"></link><published>2012-12-28T00:00:00+01:00</published><updated>2012-12-28T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-28:/tricot.html</id><summary type="html">
|
||
<p>Puisque j&#8217;ai décidé d&#8217;apprendre à faire les trucs moi-même, je me mets
|
||
au tricot. Et puis y&#8217;a aussi tout un symbole derrière: le tricot, c&#8217;est
|
||
pour les filles, tu sais, un &#8220;truc de&nbsp;gonzesse&#8221;.</p>
|
||
<p>Eh bah c&#8217;est pas gagné, jte le dis. Pour l&#8217;instant …</p></summary><content type="html">
|
||
<p>Puisque j&#8217;ai décidé d&#8217;apprendre à faire les trucs moi-même, je me mets
|
||
au tricot. Et puis y&#8217;a aussi tout un symbole derrière: le tricot, c&#8217;est
|
||
pour les filles, tu sais, un &#8220;truc de&nbsp;gonzesse&#8221;.</p>
|
||
<p>Eh bah c&#8217;est pas gagné, jte le dis. Pour l&#8217;instant j&#8217;ai réussi à faire à
|
||
peu près un rang d&#8217;endroit et j&#8217;arrive pas à enchainer sur l&#8217;envers pour
|
||
réussir à faire un point jersey (jersey c&#8217;est un rang endroit puis un
|
||
rang&nbsp;envers).</p>
|
||
<p>Enfin bref, si jamais ça vous botte vous aussi, voila quelques
|
||
ressources que j&#8217;ai trouvé sur internet (en plus des conseils avisés de
|
||
maman&nbsp;chérie™):</p>
|
||
<ul>
|
||
<li><a href="http://www.youtube.com/watch?v=VcGiBG2BNxo&amp;list=UUskaiVNnKf7amRb5OI5op_w">Montage des mailles&nbsp;&#8220;normales&#8221;</a></li>
|
||
<li><a href="http://www.youtube.com/watch?v=aIQtNN89pqA&amp;list=UUskaiVNnKf7amRb5OI5op_w">Le point&nbsp;jersey</a></li>
|
||
</ul>
|
||
<p>La nana explique plutôt bien et assez lentement. En espérant que ça&nbsp;prenne.</p></content><category term="notes"></category></entry><entry><title>Astuces SSH</title><link href="https://blog.notmyidea.org/astuces-ssh.html" rel="alternate"></link><published>2012-12-27T00:00:00+01:00</published><updated>2012-12-27T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-27:/astuces-ssh.html</id><summary type="html">
|
||
<h2 id="tunelling">Tunelling</h2>
|
||
<p>Parce que je m&#8217;en rapelle jamais (tête de&nbsp;linote):</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ssh<span class="w"> </span>-f<span class="w"> </span>hote<span class="w"> </span>-L<span class="w"> </span>local:lolnet.org:destination<span class="w"> </span>-N
|
||
</code></pre></div>
|
||
|
||
<h2 id="sshconfig">.ssh/config</h2>
|
||
<p>(merci <a href="http://majerti.fr">gaston</a>&nbsp;!)</p>
|
||
<p>La directive suivante dans .ssh/config permet de sauter d&#8217;hôte en hôte
|
||
séparés par des &#8220;+&#8221;&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>Host <span class="gs">*+*</span>
|
||
ProxyCommand ssh $(echo %h | sed
|
||
&#39;s/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l …</code></pre></div></summary><content type="html">
|
||
<h2 id="tunelling">Tunelling</h2>
|
||
<p>Parce que je m&#8217;en rapelle jamais (tête de&nbsp;linote):</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ssh<span class="w"> </span>-f<span class="w"> </span>hote<span class="w"> </span>-L<span class="w"> </span>local:lolnet.org:destination<span class="w"> </span>-N
|
||
</code></pre></div>
|
||
|
||
<h2 id="sshconfig">.ssh/config</h2>
|
||
<p>(merci <a href="http://majerti.fr">gaston</a>&nbsp;!)</p>
|
||
<p>La directive suivante dans .ssh/config permet de sauter d&#8217;hôte en hôte
|
||
séparés par des &#8220;+&#8221;&nbsp;:</p>
|
||
<div class="highlight"><pre><span></span><code>Host <span class="gs">*+*</span>
|
||
ProxyCommand ssh $(echo %h | sed
|
||
&#39;s/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /&#39;)
|
||
PATH=.:\$PATH nc -w1 $(echo %h | sed &#39;s/^.*+//;/:/!s/$/ %p/;s/:/ /&#39;)
|
||
</code></pre></div>
|
||
|
||
<p>On peut donc spécifier des &#8220;sauts&#8221; ssh du&nbsp;style:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">ssh</span><span class="w"> </span><span class="n">root</span><span class="mf">@91.25.25.25</span><span class="o">+</span><span class="mf">192.168.1.1</span>
|
||
</code></pre></div>
|
||
|
||
<p>Ensuite on peut essayer de&nbsp;rajouter:</p>
|
||
<div class="highlight"><pre><span></span><code>Host &lt;label_pour_mon_serveur_privé&gt;
|
||
user &lt;monuser(root)&gt;
|
||
IdentityFile &lt;chemin vers ma clé ssh pour le serveur publique&gt;
|
||
hostname ip_serveur_publique+ip_serveur_privé
|
||
</code></pre></div></content><category term="code"></category></entry><entry><title>Gnome 3, extensions</title><link href="https://blog.notmyidea.org/gnome-3-extensions.html" rel="alternate"></link><published>2012-12-27T00:00:00+01:00</published><updated>2012-12-27T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-27:/gnome-3-extensions.html</id><summary type="html">
|
||
<p>Après avoir tenté pendant un bout de temps unity, le bureau par defaut
|
||
de ubuntu, j&#8217;ai eu envie de changements, et j&#8217;ai donc essayé un peu de
|
||
regarder du coté de gnome 3, à&nbsp;nouveau.</p>
|
||
<p>Et finalement, j&#8217;ai trouvé quelques extensions qui sont vraiment utiles,
|
||
que je …</p></summary><content type="html">
|
||
<p>Après avoir tenté pendant un bout de temps unity, le bureau par defaut
|
||
de ubuntu, j&#8217;ai eu envie de changements, et j&#8217;ai donc essayé un peu de
|
||
regarder du coté de gnome 3, à&nbsp;nouveau.</p>
|
||
<p>Et finalement, j&#8217;ai trouvé quelques extensions qui sont vraiment utiles,
|
||
que je liste&nbsp;ici.</p>
|
||
<ul>
|
||
<li><a href="https://extensions.gnome.org/extension/547/antisocial-menu/">Antisocial
|
||
Menu</a>
|
||
vire les boutons et textes en rapport avec le web social. J&#8217;en avais
|
||
pas besoin puisque je suis connecté à mon instant messenger dans un
|
||
terminal, en utilisant&nbsp;weechat.</li>
|
||
<li><a href="https://extensions.gnome.org/extension/97/coverflow-alt-tab/">Coverflow
|
||
Alt-Tab</a>
|
||
change le switcher d&#8217;applications par defaut. Je le trouve bien plus
|
||
pratique que celui par defaut puisqu&#8217;il me permet de voir &#8220;en grand&#8221;
|
||
quelle est la fenêtre que je vais&nbsp;afficher.</li>
|
||
<li><a href="https://extensions.gnome.org/extension/55/media-player-indicator/">Media player
|
||
indicator</a>
|
||
me permet de voir en temps réel ce qui se passe dans mon lecteur
|
||
audio. Ça semble ne pas être grand chose, mais ça me manquait. Ça
|
||
s&#8217;intègre niquel avec Spotify, et ça c&#8217;est&nbsp;chouette.</li>
|
||
<li><a href="https://extensions.gnome.org/extension/149/search-firefox-bookmarks-provider/">Rechercher dans les bookmarks
|
||
firefox</a>
|
||
permet de… à votre avis&nbsp;?</li>
|
||
</ul>
|
||
<p>Un peu moins utile mais sait on&nbsp;jamais:</p>
|
||
<ul>
|
||
<li>“<a href="https://extensions.gnome.org/extension/130/advanced-settings-in-usermenu/">Advanced Settings in
|
||
UserMenu</a>”
|
||
permet d&#8217;avoir un raccourci vers les paramètres avancés dans le menu
|
||
utilisateur (en haut à&nbsp;droite)</li>
|
||
<li>Une <a href="https://extensions.gnome.org/extension/409/gtg-integration/">intégration à Getting things
|
||
Gnome</a>
|
||
(un truc de <span class="caps">GTD</span>). Je suis en train d&#8217;expérimenter avec cet outil,
|
||
donc je ne sais pas encore si ça va rester, mais pourquoi&nbsp;pas.</li>
|
||
</ul>
|
||
<p>Vous pouvez aller faire un tour sur <a href="https://extensions.gnome.org/">https://extensions.gnome.org/</a> pour
|
||
en trouver d&#8217;autres à votre&nbsp;gout.</p></content><category term="code"></category></entry><entry><title>“Groovy”</title><link href="https://blog.notmyidea.org/groovy.html" rel="alternate"></link><published>2012-12-27T00:00:00+01:00</published><updated>2012-12-27T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-27:/groovy.html</id><summary type="html">
|
||
<p>“Groovy”, c&#8217;est comme ça que je l&#8217;aime la musique: peut importe le style
|
||
finalement, la bonne musique c&#8217;est celle qui sonne, celle qui groove,
|
||
celle qui fait que tu tapes du pied (le droit chez moi) et que que ta
|
||
tête commence à&nbsp;hocher.</p>
|
||
<p>C&#8217;est pour …</p></summary><content type="html">
|
||
<p>“Groovy”, c&#8217;est comme ça que je l&#8217;aime la musique: peut importe le style
|
||
finalement, la bonne musique c&#8217;est celle qui sonne, celle qui groove,
|
||
celle qui fait que tu tapes du pied (le droit chez moi) et que que ta
|
||
tête commence à&nbsp;hocher.</p>
|
||
<p>C&#8217;est pour ça que j&#8217;ai du mal à répondre quand on me demande quel type
|
||
de musique j&#8217;aime bien. Bah voila, maintenant je sais, je l&#8217;aime groovy&nbsp;;)</p></content><category term="journal"></category></entry><entry><title>Notre dame des landes</title><link href="https://blog.notmyidea.org/notre-dame-des-landes.html" rel="alternate"></link><published>2012-12-27T00:00:00+01:00</published><updated>2012-12-27T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-27:/notre-dame-des-landes.html</id><summary type="html">
|
||
<p>La lutte à Notre Dame des Landes ne fait pas du tout que commencer, mais
|
||
il se trouve que les médias se sont &#8220;emparés&#8221; de la question que très
|
||
récemment, depuis que <span class="caps">JM</span> Ayrault s&#8217;est retrouvé premier&nbsp;ministre.</p>
|
||
<p>Voici une sélection d&#8217;articles que j&#8217;ai trouvé pertinents, à …</p></summary><content type="html">
|
||
<p>La lutte à Notre Dame des Landes ne fait pas du tout que commencer, mais
|
||
il se trouve que les médias se sont &#8220;emparés&#8221; de la question que très
|
||
récemment, depuis que <span class="caps">JM</span> Ayrault s&#8217;est retrouvé premier&nbsp;ministre.</p>
|
||
<p>Voici une sélection d&#8217;articles que j&#8217;ai trouvé pertinents, à partir de
|
||
décembre&nbsp;2012:</p>
|
||
<ul>
|
||
<li>Article dans le monde qui explique la complexité de la lutte sur
|
||
place:
|
||
<a href="http://www.lemonde.fr/idees/article/2012/12/13/notre-dame-des-landes-une-resistance-qui-ne-se-laissera-pas-dicter-sa-conduite_1805511_3232.html">http://www.lemonde.fr/idees/article/2012/12/13/notre-dame-des-landes-une-resistance-qui-ne-se-laissera-pas-dicter-sa-conduite_1805511_3232.html</a></li>
|
||
<li>autour de relations à la presse:
|
||
<a href="http://www.rennestv.fr/catalogue/magazine/notre-dame-des-landes-l-inaceptable-interdiction-de-la-presse.html">http://www.rennestv.fr/catalogue/magazine/notre-dame-des-landes-l-inaceptable-interdiction-de-la-presse.html</a></li>
|
||
<li>Notre-Dame-des-Landes : un pilote annonce un fiasco pour le futur
|
||
aéroport <a href="http://www.bastamag.net/article2866.html">http://www.bastamag.net/article2866.html</a></li>
|
||
</ul></content><category term="notes"></category></entry><entry><title>Semences paysannes</title><link href="https://blog.notmyidea.org/semences-paysannes.html" rel="alternate"></link><published>2012-12-20T00:00:00+01:00</published><updated>2012-12-20T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-20:/semences-paysannes.html</id><summary type="html">
|
||
<p><a href="http://www.dailymotion.com/video/x5nhq0_les-semences-paysannes_news#from=embed">http://www.dailymotion.com/video/x5nhq0_les-semences-paysannes_news#from=embed</a></p>
|
||
<p>A l&#8217;heure actuelle, il est interdit pour deux agriculteurs de
|
||
s&#8217;échangers des semences dans le but d&#8217;en revendre la&nbsp;production.</p>
|
||
<p>Les états ont crée la propriété interellectuelle pour relancer
|
||
l&#8217;industrie après les dégats de la guerre et les …</p></summary><content type="html">
|
||
<p><a href="http://www.dailymotion.com/video/x5nhq0_les-semences-paysannes_news#from=embed">http://www.dailymotion.com/video/x5nhq0_les-semences-paysannes_news#from=embed</a></p>
|
||
<p>A l&#8217;heure actuelle, il est interdit pour deux agriculteurs de
|
||
s&#8217;échangers des semences dans le but d&#8217;en revendre la&nbsp;production.</p>
|
||
<p>Les états ont crée la propriété interellectuelle pour relancer
|
||
l&#8217;industrie après les dégats de la guerre et les selectionneurs en ont
|
||
profité en 1960 au sein de l&#8217;<span class="caps">UPOV</span> pour faire des textes pour s&#8217;approprié
|
||
les selections qu&#8217;ils ont fait. Les textes ont été votés par les députés
|
||
depuis: bien prové au lieu de bien&nbsp;collectif.</p>
|
||
<p>Les semenciers n&#8217;existent que depuis 150 ans. Ils revendiquent
|
||
maintenant le monopole de&nbsp;selection.</p>
|
||
<p>Un catalogue est prévu pour les semences dites &#8220;de conservation&#8221; (alors
|
||
qu&#8217;elles évoluent, conservation n&#8217;est pas un terme adapté). C&#8217;est la
|
||
voie qui est possible pour pouvoir échanger des semences entre&nbsp;agriculteurs.</p>
|
||
<p>→ Quelles sont les semences de conservation depuis 2002 ? → Quid des
|
||
semences paysannes, qui évoluent et que l&#8217;on garde d&#8217;année en année, en
|
||
selectionnant les meilleures especes. → Existe-il un autre catalogue ? →
|
||
Au niveau européen, quelles sontles contraintes d&#8217;inscription ? Gratuité
|
||
demandée, qu&#8217;en est il&nbsp;?</p>
|
||
<p>→ Relocalistion sur les terroirs des&nbsp;échanges.</p>
|
||
<p>→ Biodiversité serait tué par l&#8217;utilisation d&#8217;espèces&nbsp;inscrites.</p>
|
||
<p>Série de vidéos sur la paysannerie:
|
||
<a href="http://www.latelevisionpaysanne.fr/video.php?lirevideo=86#86">http://www.latelevisionpaysanne.fr/video.php?lirevideo=86#86</a></p></content><category term="notes"></category></entry><entry><title>Languages</title><link href="https://blog.notmyidea.org/languages.html" rel="alternate"></link><published>2012-12-12T00:00:00+01:00</published><updated>2012-12-12T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-12-12:/languages.html</id><content type="html">
|
||
<p>Ouriel Ellert &#8221; Languages&#8221; avec Anthony Jambon <span class="amp">&amp;</span> Natascha Rogers, c&#8217;est enregistré par le <a href="http://www.studiomezzanine.fr">Studio Mezzanine</a> qui
|
||
comme d&#8217;hab font un travail&nbsp;impeccable.</p>
|
||
<p>Plus d&#8217;infos sur Natasha Rogers et son groupe ici:
|
||
<a href="http://www.studiomezzanine.fr/natascha-rogers/">http://www.studiomezzanine.fr/natascha-rogers/</a></p>
|
||
<iframe width="650" height="480" src="http://www.youtube.com/embed/3I5PPdsTFz0" frameborder="0" allowfullscreen></iframe></content><category term="journal"></category></entry><entry><title>Cheese & code - Wrap-up</title><link href="https://blog.notmyidea.org/cheese-code-wrap-up.html" rel="alternate"></link><published>2012-10-22T00:00:00+02:00</published><updated>2012-10-22T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-10-22:/cheese-code-wrap-up.html</id><summary type="html">
|
||
<p>This week-end I hosted a <em>cheese <span class="amp">&amp;</span> code</em> session in the country-side of
|
||
Angers,&nbsp;France.</p>
|
||
<p>We were a bunch of python hackers and it rained a lot, wich forced us to
|
||
stay inside and to code.&nbsp;Bad.</p>
|
||
<p>We were not enough to get rid of all the cheese and the awesome …</p></summary><content type="html">
|
||
<p>This week-end I hosted a <em>cheese <span class="amp">&amp;</span> code</em> session in the country-side of
|
||
Angers,&nbsp;France.</p>
|
||
<p>We were a bunch of python hackers and it rained a lot, wich forced us to
|
||
stay inside and to code.&nbsp;Bad.</p>
|
||
<p>We were not enough to get rid of all the cheese and the awesome meals,
|
||
but well, we finally managed it pretty&nbsp;well.</p>
|
||
<p>Here is a summary of what we worked&nbsp;on:</p>
|
||
<h2 id="daybed">Daybed</h2>
|
||
<p>Daybed started some time ago, and intend to be a replacement to google
|
||
forms, in term of features, but backed as a <span class="caps">REST</span> web service, in python,
|
||
and open&nbsp;source.</p>
|
||
<p>In case you wonder, daybed is effectively the name of a couch. We chose
|
||
this name because of the similarities (in the sound) with <strong>db</strong>, and
|
||
because we&#8217;re using <strong>CouchDB</strong> as a&nbsp;backend.</p>
|
||
<p><img alt="Daybed is a big couch!" src="/images/daybed.jpg"></p>
|
||
<p>We mainly hacked on daybed and are pretty close to the release of the
|
||
first version, meaning that we have something&nbsp;working.</p>
|
||
<p><a href="http://github.com/spiral-project/daybed">The code</a> is available on
|
||
github, and we also wrote <a href="http://daybed.rtfd.org">a small
|
||
documentation</a> for&nbsp;it.</p>
|
||
<p>Mainly, we did a lot of cleanup, rewrote a bunch of tests so that it
|
||
would be easier to continue to work on the project, and implemented some
|
||
minor features. I&#8217;m pretty confidend that we now have really good basis
|
||
for this&nbsp;project.</p>
|
||
<p>Also, we will have a nice todolist application, with the backend <strong>and</strong>
|
||
the frontend, in javascript / html / css, you&#8217;ll know more when it&#8217;ll be
|
||
ready&nbsp;:-)</p>
|
||
<p>Once we have something good enough, we&#8217;ll release the first version and
|
||
I&#8217;ll host it somewhere so that people can play with&nbsp;it.</p>
|
||
<h2 id="cornice">Cornice</h2>
|
||
<p>Daybed is built on top of <a href="http://cornice.rtfd.org">Cornice</a>, a
|
||
framework to ease the creation of&nbsp;web-services.</p>
|
||
<p>At Pycon France, we had the opportunity to attend a good presentation
|
||
about <a href="https://github.com/SPORE/specifications"><span class="caps">SPORE</span></a>. <span class="caps">SPORE</span> is a way
|
||
to describe your <span class="caps">REST</span> web services, as <span class="caps">WSDL</span> is for <span class="caps">WS</span>-* services. This
|
||
allows to ease the creation of generic <span class="caps">SPORE</span> clients, which are able to
|
||
consume any <span class="caps">REST</span> <span class="caps">API</span> with a <span class="caps">SPORE</span>&nbsp;endpoint.</p>
|
||
<p>Here is how you can let cornice describe your web service for&nbsp;you</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">cornice.ext.spore</span> <span class="kn">import</span> <span class="n">generate_spore_description</span>
|
||
<span class="kn">from</span> <span class="nn">cornice.service</span> <span class="kn">import</span> <span class="n">Service</span><span class="p">,</span> <span class="n">get_services</span>
|
||
|
||
<span class="n">spore</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="s1">&#39;spore&#39;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s1">&#39;/spore&#39;</span><span class="p">,</span> <span class="n">renderer</span><span class="o">=</span><span class="s1">&#39;jsonp&#39;</span><span class="p">)</span>
|
||
<span class="nd">@spore</span><span class="o">.</span><span class="n">get</span>
|
||
<span class="k">def</span> <span class="nf">get_spore</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="n">services</span> <span class="o">=</span> <span class="n">get_services</span><span class="p">()</span>
|
||
<span class="k">return</span> <span class="n">generate_spore_description</span><span class="p">(</span><span class="n">services</span><span class="p">,</span> <span class="s1">&#39;Service name&#39;</span><span class="p">,</span>
|
||
<span class="n">request</span><span class="o">.</span><span class="n">application_url</span><span class="p">,</span> <span class="s1">&#39;1.0&#39;</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>And you&#8217;ll get a definition of your service, in <span class="caps">SPORE</span>, available at&nbsp;/spore.</p>
|
||
<p>Of course, you can use it to do other things, like generating the file
|
||
locally and exporting it wherever it makes sense to you,&nbsp;etc.</p>
|
||
<p>I released today <a href="http://crate.io/packages/cornice/">Cornice 0.11</a>,
|
||
which adds into other things the support for <span class="caps">SPORE</span>, plus some other
|
||
fixes we found on our&nbsp;way.</p>
|
||
<h2 id="respire">Respire</h2>
|
||
<p>Once you have the description of the service, you can do generic clients
|
||
consuming&nbsp;them!</p>
|
||
<p>We first wanted to contribute to <a href="https://github.com/bl0b/spyre">spyre</a>
|
||
but it was written in a way that wasn&#8217;t supporting to <span class="caps">POST</span> data, and
|
||
they were using their own stack to handle <span class="caps">HTTP</span>. A lot of code that
|
||
already exists in other&nbsp;libraries.</p>
|
||
<p>While waiting the train with <a href="http://natim.ionyse.com/">Rémy</a>, we hacked
|
||
something together, named &#8220;Respire&#8221;, a thin layer on top of the awesome
|
||
<a href="http://python-requests.org">Requests</a>&nbsp;library.</p>
|
||
<p>We have a first version, feel free to have a look at it and provide
|
||
enhancements if you feel like it. We&#8217;re still hacking on it so it may
|
||
break (for the better), but that had been working pretty well for us so&nbsp;far.</p>
|
||
<p>You can <a href="http://github.com/spiral-project/respire">find the project on
|
||
github</a>, but here is how to
|
||
use it, really quickly (these examples are how to interact with&nbsp;daybed)</p>
|
||
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">respire</span> <span class="kn">import</span> <span class="n">client_from_url</span>
|
||
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="c1"># create the client from the SPORE definition</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">cl</span> <span class="o">=</span> <span class="n">client_from_url</span><span class="p">(</span><span class="s1">&#39;http://localhost:8000/spore&#39;</span><span class="p">)</span>
|
||
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="c1"># in daybed, create a new definition</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">todo_def</span> <span class="o">=</span> <span class="p">{</span>
|
||
<span class="o">...</span> <span class="s2">&quot;title&quot;</span><span class="p">:</span> <span class="s2">&quot;todo&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;description&quot;</span><span class="p">:</span> <span class="s2">&quot;A list of my stuff to do&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;fields&quot;</span><span class="p">:</span> <span class="p">[</span>
|
||
<span class="o">...</span> <span class="p">{</span>
|
||
<span class="o">...</span> <span class="s2">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;item&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;type&quot;</span><span class="p">:</span> <span class="s2">&quot;string&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;description&quot;</span><span class="p">:</span> <span class="s2">&quot;The item&quot;</span>
|
||
<span class="o">...</span> <span class="p">},</span>
|
||
<span class="o">...</span> <span class="p">{</span>
|
||
<span class="o">...</span> <span class="s2">&quot;name&quot;</span><span class="p">:</span> <span class="s2">&quot;status&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;type&quot;</span><span class="p">:</span> <span class="s2">&quot;enum&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;choices&quot;</span><span class="p">:</span> <span class="p">[</span>
|
||
<span class="o">...</span> <span class="s2">&quot;done&quot;</span><span class="p">,</span>
|
||
<span class="o">...</span> <span class="s2">&quot;todo&quot;</span>
|
||
<span class="o">...</span> <span class="p">],</span>
|
||
<span class="o">...</span> <span class="s2">&quot;description&quot;</span><span class="p">:</span> <span class="s2">&quot;is it done or not&quot;</span>
|
||
<span class="o">...</span> <span class="p">}</span>
|
||
<span class="o">...</span> <span class="p">]}</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">cl</span><span class="o">.</span><span class="n">put_definition</span><span class="p">(</span><span class="n">model_name</span><span class="o">=</span><span class="s1">&#39;todo&#39;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">todo_def</span><span class="p">)</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">cl</span><span class="o">.</span><span class="n">post_data</span><span class="p">(</span><span class="n">model_name</span><span class="o">=</span><span class="s1">&#39;todo&#39;</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="o">=</span><span class="s1">&#39;make it work&#39;</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="s1">&#39;todo&#39;</span><span class="p">))</span>
|
||
<span class="p">{</span><span class="sa">u</span><span class="s1">&#39;id&#39;</span><span class="p">:</span> <span class="sa">u</span><span class="s1">&#39;9f2c90c0529a442cfdc03c191b022cf7&#39;</span><span class="p">}</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">cl</span><span class="o">.</span><span class="n">get_data</span><span class="p">(</span><span class="n">model_name</span><span class="o">=</span><span class="s1">&#39;todo&#39;</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>Finally, we were out of cheese so everyone headed back to their
|
||
respective houses and&nbsp;cities.</p>
|
||
<p>Until next&nbsp;time?</p></content><category term="code"></category></entry><entry><title>Bière maison !</title><link href="https://blog.notmyidea.org/biere-maison.html" rel="alternate"></link><published>2012-10-04T00:00:00+02:00</published><updated>2012-10-04T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-10-04:/biere-maison.html</id><summary type="html">
|
||
<p>Et voilà, c&#8217;est notre troisième brassin. On a commencé à faire notre
|
||
propre bière (avec un ami, Fred) il y a quasiment un an maintenant, et
|
||
après quelques dératés, même s&#8217;il nous reste encore bien du chemin à
|
||
parcourir pour avoir quelque chose qui nous convienne réellement… c …</p></summary><content type="html">
|
||
<p>Et voilà, c&#8217;est notre troisième brassin. On a commencé à faire notre
|
||
propre bière (avec un ami, Fred) il y a quasiment un an maintenant, et
|
||
après quelques dératés, même s&#8217;il nous reste encore bien du chemin à
|
||
parcourir pour avoir quelque chose qui nous convienne réellement… c&#8217;est
|
||
pas si pire comme on dit&nbsp;!</p>
|
||
<p>Cette fois-çi, on s&#8217;est penché sur la confection d&#8217;une <span class="caps">IPA</span> (Indian Pale
|
||
Ale, une bière un peu plus amère que celle qu&#8217;on à l&#8217;habitude de trouver
|
||
en&nbsp;France).</p>
|
||
<p>Elle est plus amère car elle comporte plus de houblon que les autres, et
|
||
(dans notre cas en tout cas) parce qu&#8217;on fait la première fermentation
|
||
en présence de&nbsp;houblon.</p>
|
||
<h2 id="comment-quon-fait-de-la-biere">Comment qu&#8217;on fait de la bière&nbsp;?</h2>
|
||
<p>Machine arrière; n&#8217;allons pas trop vite: comment est-ce qu&#8217;on fait de la
|
||
bière, d&#8217;abord&nbsp;?</p>
|
||
<p>En fin de compte, les quelques étapes nécessaire à la confection de la
|
||
bière ne sont pas bien sorcières; concassage de l&#8217;orge maltée, cuisson
|
||
(libération de l&#8217;amidon dans l&#8217;eau), infusion du houblon,
|
||
refroidissement, première fermentation, embouteillage et seconde&nbsp;fermentation.</p>
|
||
<p>L&#8217;idée principale est transformer l&#8217;amidon d&#8217;orge maltée en sucre, pour
|
||
le &#8220;donner à manger&#8221; à des levures. Vous ajoutez un peu de houblon au
|
||
milieu pour donner un petit goût amer et le tour est joué. Enfin&nbsp;presque.</p>
|
||
<h2 id="etape-par-etape">Étape par&nbsp;étape</h2>
|
||
<p>Première étape: <strong>le concassage</strong>. On avait 6kg d&#8217;orge maltée à
|
||
concasser (plus exactement 6kg de malt pâle <em><span class="caps">7EDC</span></em> et 500g de malt cara
|
||
<em><span class="caps">50EDC</span></em>).</p>
|
||
<p><img alt="Image de concassage." src="/images/concassage.jpg"></p>
|
||
<p>Attention, pas trop fin dis donc ! On ne veut pas de la poudre, on veut
|
||
simplement permettre à l&#8217;amidon de se dissoudre dans l&#8217;eau. Si on
|
||
concasse le malt trop fin, on se retrouve avec un dépôt dégeulasse au
|
||
fond de toutes les bouteilles (c&#8217;est l&#8217;expérience qui parle, notre
|
||
première bière avait plus goût de céréale que de&nbsp;bière…)</p>
|
||
<p>Contrairement aux fois précédentes où nous avions utilisé la technique
|
||
du marteau et du torchon (oui, comme vous pouvez l&#8217;imaginer, c&#8217;est assez
|
||
long et fastidieux), On a utilisé… un moulin à malt ! Qui nous à permis
|
||
de concasser les 6kg en 30 minutes (heureusement qu&#8217;on était trois pour
|
||
se relayer sur le moulin, parce que nos petits muscles fatiguaient assez
|
||
vite; vous pouvez envisager de faire ça tout seul si vous êtes un&nbsp;tennisman).</p>
|
||
<p><img alt="C'est dur !" src="/images/concasse.jpg"></p>
|
||
<p>La seconde étape, <strong>l&#8217;empatage</strong>. Il s&#8217;agit de faire chauffer notre orge
|
||
maltée à différentes températures. Les fois précédentes, on avait
|
||
utilisé plusieurs paliers de température, mais il semble que ça ne soit
|
||
pas si nécessaire que ça, selon les informations de l&#8217;ami Fred. On à
|
||
donc tenté de faire chauffer notre malt directement à 50°C. Une petite
|
||
erreur sur la route, on à eu peur de la contamination bactérienne et on
|
||
à décidé de faire bouillir nos 26L d&#8217;eau pour être sur que les
|
||
bactéries s&#8217;enfuient en courant. Je dis erreur parce que ça nous à pris
|
||
pas loin de 3h30, inertie quand tu nous&nbsp;tiens!</p>
|
||
<p>On se rends compte de la taille de la marmite un peu&nbsp;là:</p>
|
||
<p><img alt="Une grosse marmite" src="/images/marmite.jpg"></p>
|
||
<p>Une fois l&#8217;eau à température (54°C), il faut ajouter le malt et le
|
||
laisser durant 30mn à cette température, puis augmenter jusqu&#8217;à 65°C
|
||
durant&nbsp;1h.</p>
|
||
<p>La troisième étape, c&#8217;est <strong>le rinçage</strong>, l&#8217;idée est de récupérer
|
||
l&#8217;amidon qui s&#8217;est dissout dans l&#8217;eau et de mettre de côté l&#8217;orge maltée
|
||
(la partie solide). Pour ça, il faut faire chauffer de l&#8217;eau de rinçage.
|
||
On a utilisé 10L d&#8217;eau de rinçage qu&#8217;on a fait chauffer à 78°C, en
|
||
comptant sur le fait qu&#8217;elle perdra de sa température (20°C à peu près)
|
||
en étant utilisée. On a filtré deux fois pour être sûr de ne rien&nbsp;perdre.</p>
|
||
<p><img alt="Filtrage filtrage..." src="/images/filtrage.jpg"></p>
|
||
<p>L&#8217;étape d&#8217;après (la quatrième, vous suivez), c&#8217;est <strong>le houblonnage</strong>.
|
||
On va faire infuser notre &#8220;solution aqueuse&#8221; (wouah, on dirait de la
|
||
chimie !) avec du houblon. Il faut porter l&#8217;eau à ébullition et laisser
|
||
faire durant&nbsp;1h.</p>
|
||
<p>Dernière étape: <strong>le refroidissement</strong>. On dirait que c&#8217;est tranquilou
|
||
comme ça, mais en fait ça ne l&#8217;est pas tant que ça: il faut réussir à
|
||
passer notre liquide qui était en ébullition à 54°C en un temps
|
||
acceptable. Pour ça, on a utilisé un serpentin confectionné&nbsp;main.</p>
|
||
<p><img alt="Notre refroidisseur fait main par Fred." src="/images/refroidisseur.jpg"></p>
|
||
<p>Ça nous a permis de passer de 100°C à 54°C en… 35 minutes quand même !
|
||
(Nous avions essayé les fois précédentes de gérer ça à coup de baignoire
|
||
et de glaçons, les temps n&#8217;étaient absolument pas au&nbsp;rendez-vous).</p>
|
||
<p><img alt="Décidement pas." src="/images/refroidissement.jpg"></p>
|
||
<p>Je disais dernière étape, mais il ne faut pas oublier de rajouter les
|
||
levures, qui elles vont faire tout le travail et transformer tout ça en…
|
||
alcool ! Dans notre cas, on ajoute aussi dans la cuve de fermentation
|
||
du houblon question de donner l&#8217;amertume dont on a&nbsp;envie.</p>
|
||
<p>On à mesuré une densité de 1046, ce qui veut dire 6° d&#8217;alcool. La cuve
|
||
est maintenant en train de buller tranquillement (les levures produisent
|
||
du gaz qui est évacué), et ça doit durer 15 jours&nbsp;approximativement.</p>
|
||
<h2 id="mise-en-bouteille">Mise en&nbsp;bouteille</h2>
|
||
<p>Une fois ces deux semaines passées, il faut mettre en bouteille. Dans
|
||
notre cas nous avons récupéré des bouteilles à bouchon mécanique (vous
|
||
savez, les bouteilles de limonades) qu&#8217;on à bien rincé et&nbsp;nettoyé.</p>
|
||
<p>On s&#8217;équipe d&#8217;un siphon (pensez à prendre un tuyau avec un diamètre
|
||
assez important, le notre était petit et c&#8217;était assez long) et après
|
||
avoir ajouté du sucre dans le mélange (pour réactiver les levures), on
|
||
remplit les bouteilles ! Il s&#8217;agit de la seconde fermentation, celle
|
||
qui va faire les bulles (la première fermentation se charge de l&#8217;alcool,
|
||
la seconde des&nbsp;bulles).</p>
|
||
<p>Et voilà ! Il ne reste plus qu&#8217;à mettre les bouteilles de coté durant
|
||
deux semaines de plus et… à déguster le moment&nbsp;venu.</p>
|
||
<p>On a donc pu tester notre bière la semaine dernière et, ma foi, elle est
|
||
pas mal du tout. Elle ne mousse pas trop et à un goût un peu amer.
|
||
Malheureusement pas assez à mon goût, mais ça viendra. En comparaison à
|
||
nos précédents essais, c&#8217;est plutôt positif: la première était ratée
|
||
puisque trop de pression et trop de dépôt (et donc un fort goût de
|
||
levures) alors que la seconde (on avait tenté d&#8217;ajouter de la lavande)
|
||
avait un goût de lavande amère, pour ne pas dire de&nbsp;savon.</p>
|
||
<p>Cette dernière bière a un goût de… de bière ! Il nous reste encore à
|
||
comprendre comment faire pour lui donner la saveur que l&#8217;on souhaite,
|
||
mais c&#8217;est déjà un grand pas en avant. Prochaine étape&#8230; La bière de
|
||
Noël&nbsp;!</p></content><category term="journal"></category></entry><entry><title>Motivation, bénévolat et participation</title><link href="https://blog.notmyidea.org/motivation-benevolat-et-participation.html" rel="alternate"></link><published>2012-10-04T00:00:00+02:00</published><updated>2012-10-04T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-10-04:/motivation-benevolat-et-participation.html</id><summary type="html">
|
||
<p>Des luttes, dieu (même si on peut à juste titre se demander ce qu&#8217;il
|
||
vient faire là) sait qu&#8217;il y en a. Principalement pour pointer du doigt
|
||
les hérésies du système actuel. Ça s&#8217;applique à l&#8217;informatique et à son
|
||
système de brevets, au <a href="http://zad.nadir.org/">bétonnage de nos …</a></p></summary><content type="html">
|
||
<p>Des luttes, dieu (même si on peut à juste titre se demander ce qu&#8217;il
|
||
vient faire là) sait qu&#8217;il y en a. Principalement pour pointer du doigt
|
||
les hérésies du système actuel. Ça s&#8217;applique à l&#8217;informatique et à son
|
||
système de brevets, au <a href="http://zad.nadir.org/">bétonnage de nos
|
||
campagnes</a> ou encore aux luttes contre
|
||
l&#8217;oligarchie et les profits d&#8217;une minorité aux dépends du reste du
|
||
monde, et à encore bien d&#8217;autres&nbsp;choses.</p>
|
||
<p>Pendant un bout de temps, j&#8217;ai parlé d&#8217;entraide, de collaboration, j&#8217;ai
|
||
essayé de sensibiliser autour de la question environnementale et aux
|
||
alternatives sociales. C&#8217;est d&#8217;ailleurs de cette manière que je me suis
|
||
moi-même le plus sensibilisé à ces questions qui me&nbsp;préoccupaient.</p>
|
||
<p>J&#8217;ai tenté de le faire sans tomber dans la critique des choix des uns et
|
||
des autres. Je respecte profondément la diversité des points de vues
|
||
<strong>mais</strong> je souhaite également que ces choix soient faits en
|
||
connaissance de&nbsp;cause.</p>
|
||
<p>Une des choses difficile à supporter (pour les autres) quand on fait de
|
||
la sensibilisation, c&#8217;est le syndrôme du jeune con, du donneur de&nbsp;leçons.</p>
|
||
<p>On dirait qu&#8217;on parle de sauver le monde. &#8220;Nous qui avons tout compris,
|
||
on peut vous aider à aller dans la <em>bonne direction</em>&#8220;, mais c&#8217;est en
|
||
oubliant que la bonne direction pour l&#8217;un ne l&#8217;est pas nécessairement
|
||
pour les&nbsp;autres…</p>
|
||
<h2 id="just-do-it">Just do it&nbsp;!</h2>
|
||
<p>Se battre <em>contre quelque chose</em> permet de facilement trouver des
|
||
personnes qui partagent les même craintes alors que se battre <em>pour</em>
|
||
permet d&#8217;engager des discussions avec des personnes qui partagent une
|
||
vision&nbsp;commune.</p>
|
||
<p>Proposer des choses, trouver des personnes qui partagent des points de
|
||
vue est un bon point de départ pour le changer ce monde, a notre
|
||
échelle. Le récent documentaire <a href="http://justdoitfilm.com/">&#8220;Just do
|
||
it&#8221;</a> porte un message assez clair: toute
|
||
initiative compte, aussi petite et insignifiante qu&#8217;elle puisse&nbsp;sembler.</p>
|
||
<p>Des initiatives locales, il y en a, plein. Et si ce que nous avons dans
|
||
notre quotidien nous pèse (aller au supermarché, subir la
|
||
sur-médiatisation télévisuelle, ne pas parler à nos voisins de
|
||
quartier…), qu&#8217;est-ce qui nous empêche d&#8217;y substituer des modèles
|
||
alternatifs&nbsp;?</p>
|
||
<p>Monter une <a href="https://fr.wikipedia.org/wiki/AMAP"><span class="caps">AMAP</span></a> (Association Pour
|
||
le Maintien d&#8217;une Agriculture Paysanne) n&#8217;est pas aussi compliqué qu&#8217;il
|
||
y parait. Pour avoir fait l&#8217;expérience par deux fois, j&#8217;ai été très
|
||
agréablement surpris par la facilité des choses, pour peu qu&#8217;on ne
|
||
cherche pas à s&#8217;encombrer de l&#8217;inutile (tiens encore une fois on parle
|
||
de frugalité !): il est facile de vouloir faire trop, de recréer les
|
||
processus complexes auxquels nous sommes souvent&nbsp;confrontés.</p>
|
||
<p>Vous souhaitez partager des connaissances (cuisine, musique, danse,
|
||
bricolage, écriture), il suffit de le faire. En fait, pour la plupart
|
||
des choses, il suffit de tenter l&#8217;expérience, c&#8217;est rarement décevant.
|
||
Surtout quand on s&#8217;embarque dans des choses saugrenues ou
|
||
personnellement&nbsp;inédites.</p>
|
||
<p>Pour moi, la frugalité, la simplicité volontaire, la sobriété heureuse,
|
||
appelez-ça comme vous le voulez, représente ce qui me convient et me
|
||
permet d&#8217;être en ligne avec les idées que je&nbsp;défends.</p>
|
||
<h2 id="faciliter-la-participation">Faciliter la&nbsp;participation</h2>
|
||
<p>Beaucoup de personnes sont à même de participer à des projets locaux,
|
||
pour peu qu&#8217;ils soient au courant mais pour autant peu franchissent le
|
||
pas, et encore moins persévèrent, pourquoi&nbsp;?</p>
|
||
<p>Et pourquoi pas laisser les présents, les motivés, s&#8217;investir par
|
||
eux-mêmes ? Avoir des responsabilités est souvent pour ma part un frein
|
||
à la réalisation d&#8217;un projet lorsque je suis&nbsp;bénévole.</p>
|
||
<p>Décider à l&#8217;avance des choses qui semblent utiles et/ou importantes est
|
||
parfois indispensable, mais ne pas trop en faire permet de laisser libre
|
||
court à l&#8217;imagination (souvent débordante) des&nbsp;participants.</p>
|
||
<p>J&#8217;aime beaucoup l&#8217;idée de faire des camps de quelques jours, où rien
|
||
n&#8217;est réellement décidé à l&#8217;avance, mise à part un thème et quelques
|
||
temps de plénière ou il est possible à chacun de s&#8217;exprimer sur les
|
||
projets qui pourraient êtres&nbsp;réalisés.</p>
|
||
<p>Pas besoin de tant de formalisation: mettez une équipe de bidouilleurs
|
||
ensemble durant une semaine sans objectif commun à priori et sans
|
||
distractions, vous verrez bien ce qui en ressortira&nbsp;!</p></content><category term="journal"></category></entry><entry><title>Cheese & Code party: October 20-21</title><link href="https://blog.notmyidea.org/cheese-code-party-october-20-21.html" rel="alternate"></link><published>2012-09-20T00:00:00+02:00</published><updated>2012-09-20T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-09-20:/cheese-code-party-october-20-21.html</id><summary type="html">
|
||
<p>At PyconFR, this week-end, a few ideas were thrown in the air and one of
|
||
them was to have a /dev/fort doing some python-related&nbsp;coding.</p>
|
||
<p>The concept of a /dev/fort is to put a bunch of hackers together and see
|
||
what comes out from it. Tarek is doing …</p></summary><content type="html">
|
||
<p>At PyconFR, this week-end, a few ideas were thrown in the air and one of
|
||
them was to have a /dev/fort doing some python-related&nbsp;coding.</p>
|
||
<p>The concept of a /dev/fort is to put a bunch of hackers together and see
|
||
what comes out from it. Tarek is doing something related with the Afpy
|
||
Computer Camps at his house each year, I&#8217;ve been there twice and it
|
||
really was a nice&nbsp;experience.</p>
|
||
<p>At Djangocong 2012, in Montpellier (south of France), <a href="http://blog.mathieu-leplatre.info/">Mathieu
|
||
Leplatre</a> and myself started to work
|
||
on a model validation and storage service, named
|
||
<a href="https://github.com/spiral-project/daybed/">Daybed</a>.</p>
|
||
<p>I&#8217;ve talked about this project to some persons this week-end (I&#8217;ve even
|
||
done <a href="http://alexis.notmyidea.org/lightning-daybed.html">a lightning
|
||
talk</a> about it) and
|
||
it gathered some interest from people in the python community, so we
|
||
thought about sprinting on&nbsp;this.</p>
|
||
<h2 id="20-and-21-october-a-computer-camp">20 and 21 October - A Computer Camp&nbsp;!</h2>
|
||
<p>Add to this a few beers, and the sprint turns magically into a camp.
|
||
We&#8217;ll be sprinting at the end of October (the 20 and 21) near Angers, on&nbsp;daybed.</p>
|
||
<p>We plan to have great food and wine, so if you feel like it and if you
|
||
want to come and work on some python-related things, you&#8217;re&nbsp;invited!</p>
|
||
<p>Although, I can host a limited number of persons, so you&#8217;ll need to
|
||
contact me before :), that&#8217;s alexis at notmyidea dot&nbsp;org.</p>
|
||
<p>I&#8217;ve setup a wiki page to organize a bit everything (knowing how many
|
||
people will come by will allow me to handle things better), please put
|
||
information&nbsp;there:</p>
|
||
<p><a href="http://wiki.python.org/moin/ComputerCampAlexis">http://wiki.python.org/moin/ComputerCampAlexis</a></p></content><category term="journal"></category></entry><entry><title>Circus sprint at PyconFR</title><link href="https://blog.notmyidea.org/circus-sprint-at-pyconfr.html" rel="alternate"></link><published>2012-09-17T00:00:00+02:00</published><updated>2012-09-17T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-09-17:/circus-sprint-at-pyconfr.html</id><summary type="html">
|
||
<p>Last Thursday to Sunday, <a href="http://pycon.fr">Pycon France</a> took place, in
|
||
Paris. It was the opportunity to meet a lot of people and to talk about
|
||
python awesomness in&nbsp;general.</p>
|
||
<p>We had three tracks this year, plus sprints the two first days. We
|
||
sprinted on <a href="http://circus.io">Circus</a>, the process and socket manager
|
||
we …</p></summary><content type="html">
|
||
<p>Last Thursday to Sunday, <a href="http://pycon.fr">Pycon France</a> took place, in
|
||
Paris. It was the opportunity to meet a lot of people and to talk about
|
||
python awesomness in&nbsp;general.</p>
|
||
<p>We had three tracks this year, plus sprints the two first days. We
|
||
sprinted on <a href="http://circus.io">Circus</a>, the process and socket manager
|
||
we&#8217;re using at Mozilla for some of our&nbsp;setups.</p>
|
||
<p>The project gathered some interest, and we ended up with 5 persons
|
||
working on it. Of course, we spent some time explaining what is Circus,
|
||
how it had been built, a lot of time talking about use-cases and
|
||
possible improvements, but we also managed to add new&nbsp;features.</p>
|
||
<p>Having people wanting to sprint on our projects is exciting because
|
||
that&#8217;s when making things in the open unleashes its full potential. You
|
||
can&#8217;t imagine how happy I was to have some friends come and work on this
|
||
with us&nbsp;:)</p>
|
||
<p>Here is a wrap-up of the&nbsp;sprint:</p>
|
||
<h2 id="autocompletion-on-the-command-line">Autocompletion on the&nbsp;command-line</h2>
|
||
<p><a href="http://natim.ionyse.com">Remy Hubscher</a> worked on the command-line
|
||
autocompletion. Now we have a fancy command-line interface which is able
|
||
to aucomplete if you&#8217;re using bash. It seems that not that much work is
|
||
needed to make it happen on zsh as well&nbsp;:)</p>
|
||
<p><a href="https://github.com/mozilla-services/circus/blob/master/extras/circusctl_bash_completion">Have a look at the&nbsp;feature</a></p>
|
||
<p>On the same topic, we now have a cool shell for Circus. If you start the
|
||
circusctl command without any option, you&#8217;ll end-up with a cool shell.
|
||
Thanks <a href="https://github.com/jojax">Jonathan Dorival</a> for the work on
|
||
this! You can have a look at <a href="https://github.com/mozilla-services/circus/pull/268">the pull
|
||
request</a>.</p>
|
||
<h2 id="future-changes-to-the-web-ui">Future changes to the web&nbsp;ui</h2>
|
||
<p><a href="https://twitter.com/rachbelaid">Rachid Belaid</a> had a deep look at the
|
||
source code and is much more familiarized to it now than before. We
|
||
discussed the possibility to change the implementation of the web ui,
|
||
and I&#8217;m glad of this. Currently, it&#8217;s done with bottle.py and we want to
|
||
switch to&nbsp;pyramid.</p>
|
||
<p>He fixed some issues that were in the tracker, so we now can have the
|
||
age of watchers in the webui, for&nbsp;instance.</p>
|
||
<h2 id="bug-and-doc-fixing">Bug and doc&nbsp;fixing</h2>
|
||
<p>While reading the source code, we found some inconsistencies and fixed
|
||
them, with <a href="http://mathieu.agopian.info/">Mathieu Agopian</a>. We also
|
||
tried to improve the documentation at different&nbsp;levels.</p>
|
||
<p>Documentation still needs a lot of love, and I&#8217;m planning to spend some
|
||
time on this shortly. I&#8217;ve gathered a bunch of feedback on&nbsp;this</p>
|
||
<h2 id="circus-clustering-capabilities">Circus clustering&nbsp;capabilities</h2>
|
||
<p>One feature I wanted to work on during this sprint was the clustering
|
||
abilities of Circus. Nick Pellegrino made an internship on this topic at
|
||
Mozilla so we spent some time to review his pull&nbsp;requests.</p>
|
||
<p>A lot of code was written for this so we discussed a bunch of things
|
||
regarding all of this. It took us more time than expected (and I still
|
||
need to spend more time on this to provide appropriate feedback), but it
|
||
allowed us to have a starting-point about what this clustering thing
|
||
could&nbsp;be.</p>
|
||
<p>Remy wrote <a href="http://tech.novapost.fr/circus-clustering-management-en.html">a good summary about our
|
||
brainstorming</a>
|
||
so I&#8217;ll not do it again here, but feel free to contact us if you have
|
||
ideas on this, they&#8217;re very&nbsp;welcome!</p>
|
||
<h2 id="project-management">Project&nbsp;management</h2>
|
||
<p>We&#8217;ve had some inquiries telling us that&#8217;s not as easy as it should to
|
||
get started with the Circus project. Some of the reasons are that we
|
||
don&#8217;t have any release schedule, and that the documentation is hairy
|
||
enough to lost people, at some point&nbsp;:)</p>
|
||
<p>That&#8217;s something we&#8217;ll try to fix soon&nbsp;:)</p>
|
||
<p>PyconFR was a very enjoyable event. I&#8217;m looking forward to meet the
|
||
community again and discuss how Circus can evolve in ways that are
|
||
interesting to&nbsp;everyone.</p>
|
||
<p>Tarek and me are going to <a href="http://python.ie/pycon/2012/">Pycon ireland</a>,
|
||
feel free to reach us if you&#8217;re going there, we&#8217;ll be happy to meet and
|
||
enjoy&nbsp;beers!</p></content><category term="code"></category></entry><entry><title>Pourquoi Mozilla?</title><link href="https://blog.notmyidea.org/pourquoi-mozilla.html" rel="alternate"></link><published>2012-07-16T00:00:00+02:00</published><updated>2012-07-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-07-16:/pourquoi-mozilla.html</id><summary type="html">
|
||
<p>Depuis que j&#8217;ai commencé à bosser chez Mozilla, je me retrouve assez
|
||
souvent à expliquer ce que j&#8217;y fais. J&#8217;aime bien raconter l&#8217;histoire de
|
||
Mozilla, la mission, et comment je m&#8217;y&nbsp;rattache.</p>
|
||
<p>Je prends bien sur un malin plaisir à expliquer à chaque fois les …</p></summary><content type="html">
|
||
<p>Depuis que j&#8217;ai commencé à bosser chez Mozilla, je me retrouve assez
|
||
souvent à expliquer ce que j&#8217;y fais. J&#8217;aime bien raconter l&#8217;histoire de
|
||
Mozilla, la mission, et comment je m&#8217;y&nbsp;rattache.</p>
|
||
<p>Je prends bien sur un malin plaisir à expliquer à chaque fois les
|
||
tenants et les aboutissants, aussi je me suis dit que ça pouvait avoir
|
||
du sens de l&#8217;écrire quelque&nbsp;part.</p>
|
||
<p>Ça parle bien sur de logiciel libre, de protection de la vie privée et
|
||
de&nbsp;contre-pouvoirs.</p>
|
||
<p>Je ne m&#8217;adresse pas ici aux afficionados du logiciel libre et du non
|
||
contrôle du web, mais aux potentiels intéressés, qui souhaitent
|
||
comprendre ce qu&#8217;on fait à Mozilla, pourquoi et comment, et plus
|
||
particulièrement quel est le rôle que je joue la&nbsp;dedans.</p>
|
||
<h2 id="logiciel-libre">Logiciel&nbsp;libre</h2>
|
||
<p>Une des premières choses qui vient à l&#8217;esprit des gens quand on parle de
|
||
Mozilla, et par extension de Firefox, c&#8217;est qu&#8217;il s&#8217;agit d&#8217;un logiciel
|
||
gratuit. D&#8217;un logiciel soit disant &#8220;libre&#8221;. Avouez que le concept est de
|
||
prime abord curieux. Un logiciel qui serait libéré, mais libéré de quoi&nbsp;?</p>
|
||
<p>Je ne vais pas refaire la génèse du logiciel et du logiciel libre, mais
|
||
pour résumer et expliquer ça très grossièrement, le logiciel libre c&#8217;est
|
||
pour moi l&#8217;idée de la collaboration. &#8220;Plutôt que de travailler chacun
|
||
dans son coin, construisons ensemble quelque chose qui nous sera utile à
|
||
tous&#8221;. Ça marche dans le domaine de l&#8217;informatique parce qu&#8217;on est
|
||
exposé à un bien commun non matériel. Ce n&#8217;est pas parce que je te
|
||
donne un logiciel que je ne l&#8217;ai plus. La duplication est possible et
|
||
elle rend la collaboration plus&nbsp;facile.</p>
|
||
<h3 id="euh-oui-mais">Euh, oui&nbsp;mais…</h3>
|
||
<p>Ok, ok. Et comment on coopère ? Derrière un logiciel, il faut écrire des
|
||
lignes de code, il faut décrire comment doit se comporter le logiciel
|
||
dans l&#8217;ensemble des cas qu&#8217;il peut rencontrer. Mais pas seulement.
|
||
Beaucoup de personnes travaillent pour faire en sorte que Firefox soit
|
||
disponible dans près de 100 langues et dialectes par&nbsp;exemple.</p>
|
||
<p>J&#8217;aime beaucoup penser que le logiciel libre réussit à réunir des
|
||
personnes avec des objectifs differents. Linux, qui est un logiciel
|
||
libre, est par exemple utilisé dans beaucoup de domaines très différents
|
||
tels que la médecine, l&#8217;automobile ou&nbsp;l&#8217;énergie.</p>
|
||
<p>Le logiciel libre est une valeur clé que nous défendons chez&nbsp;Mozilla.</p>
|
||
<h2 id="protection-de-la-vie-privee">Protection de la vie&nbsp;privée</h2>
|
||
<p>Mozilla en fait un peu sa devise. Nous ne sommes pas une entreprise,
|
||
nous n&#8217;avons aucun intérêt à enfermer les utilisateurs chez nous, et
|
||
surtout nous n&#8217;exploitons et n&#8217;exploiterons pas les données utilisateurs
|
||
à des fins commerciales.&nbsp;Jamais.</p>
|
||
<h3 id="stockage-des-donnees">Stockage des&nbsp;données</h3>
|
||
<p>Un exemple qui est frappant est celui de
|
||
<a href="https://www.mozilla.org/en-US/mobile/sync/">Sync</a>, l&#8217;outil qui permet
|
||
de synchroniser les données de navigation entre plusieurs périphériques
|
||
(Cela peut être utile pour avoir votre historique de navigation partagé
|
||
entre votre ordinateur de bureau et un téléphone portable par&nbsp;exemple)</p>
|
||
<p>Les données qui sont stockées dans un service tel que sync sont
|
||
cruciales: vos mots de passe et votre historique de navigation par
|
||
exemple. Imaginez ce que des annonceurs publicitaires pourraient faire
|
||
avec ces données. Il est assez facile de connaître votre profil et donc
|
||
d&#8217;ensuite faire de la publicité ciblée à partir de ces informations.
|
||
Voire pire. Donner ces données à qui fait suffisemment pression sur vous
|
||
pour les&nbsp;récupérer.</p>
|
||
<p>Heureusement, les données qui sont stockées sur les serveurs Sync sont
|
||
chifrées, et seul l&#8217;utilisateur a accès a la clé de chiffrement et de
|
||
déchiffrement. En d&#8217;autres termes, en ayant accès aux serveurs de
|
||
Mozilla, même de l&#8217;intérieur, je pourrais avoir accès à vos données mais
|
||
je ne pourrais rien en faire car celles-ci me sont impossibles à&nbsp;déchiffrer.</p>
|
||
<p>Mozilla essaye de mettre le doigt là où ça fait mal dans l&#8217;innovation
|
||
web : la publicité et le respect de la vie privée des utilisateurs.
|
||
Facebook, Google, Twitter sont autant d&#8217;entreprises qui gagnent de
|
||
l&#8217;argent grâce à leurs utilisateurs et à leurs données&nbsp;privées.</p>
|
||
<p>Cela n&#8217;est pas <em>nécessairement</em> un mal mais il me semble important
|
||
d&#8217;informer les utilisateurs d&#8217;Internet la dessus, et de leur proposer
|
||
des méthodes qui leur permettent de protéger leur vie&nbsp;privée.</p>
|
||
<h3 id="decentralisation">Décentralisation</h3>
|
||
<p>Un autre aspect important est le fait que vous n&#8217;avez pas besoin de
|
||
dépendre des serveurs de Mozilla si vous ne souhaitez pas en dépendre.
|
||
Bien que nous fassions tout ce qui est en notre pouvoir pour avoir des
|
||
serveurs très réactifs et capables de tenir la charge, nous ne sommes
|
||
pas à l&#8217;abri de pannes. Auquel cas il vous faudra simplement vous armer
|
||
de&nbsp;patience.</p>
|
||
<p>Mais il est possible pour vous de maintenir votre propre serveur et de
|
||
ne pas dépendre de Mozilla pour stocker vos données privées. J&#8217;ai parlé
|
||
de Sync mais Mozilla (j&#8217;en parle un peu plus bas) travaille aussi sur un
|
||
système d&#8217;exploitation pour téléphone portable, nommé Firefox <span class="caps">OS</span>
|
||
(anciennement Boot 2 Gecko), et sur l&#8217;écosystème qui va&nbsp;avec.</p>
|
||
<p>Actuellement, si vous souhaitez synchroniser vos contacts par exemple,
|
||
vous dépendez quasiment toujours d&#8217;une autorité à qui vous ne faites
|
||
peut être pas confiance: Apple, Microsoft ou bien&nbsp;Google.</p>
|
||
<p>On ne vous propose pas simplement de nous faire confiance, on vous
|
||
propose la possibilité de ne faire confiance qu&#8217;à ceux à qui vous
|
||
souhaitez accorder votre confiance, et ça peut être vous si vous le&nbsp;souhaitez.</p>
|
||
<p>La décentralisation à ceci de bon qu&#8217;elle vous laisse le choix d&#8217;où vous
|
||
souhaitez stocker vos&nbsp;données.</p>
|
||
<h2 id="innovation-et-standardisation">Innovation et&nbsp;standardisation</h2>
|
||
<p>Mozilla, dès ses débuts, a été un laboratoire. Firefox (si je ne me
|
||
trompe pas) a été le premier navigateur à avoir des onglets. Le web,
|
||
c&#8217;est cool parce que ça bouge tout le temps ! (Edit: en fait, <a href="http://en.wikipedia.org/wiki/Tabbed_document_interface">ce
|
||
n&#8217;était pas le
|
||
premier</a>, mais
|
||
l&#8217;idée est&nbsp;là)</p>
|
||
<p>La dernière innovation en date est Firefox <span class="caps">OS</span>: utilisons les
|
||
technologies du web pour créer un téléphone: utilisons le web comme
|
||
plateforme, et profitons de tout l&#8217;écosystème qui existe déjà autour de&nbsp;celui-ci.</p>
|
||
<p>C&#8217;est bien que ça bouge mais il faut qu&#8217;on se mette d&#8217;accord sur comment
|
||
on veut faire bouger les choses. La guerre des navigateurs a eu lieu. Ne
|
||
pas reproduire ça est parfois un challenge. La standardisation, tout le
|
||
monde s&#8217;y&nbsp;met.</p>
|
||
<p>On a gagné une guerre: aux utilisateurs de choisir les outils qu&#8217;ils
|
||
souhaitent et non pas aux développeurs d&#8217;imposer leurs&nbsp;choix.</p>
|
||
<h2 id="et-moi-quest-ce-que-je-fais-la-dedans">Et moi, qu&#8217;est-ce que je fais la dedans&nbsp;?</h2>
|
||
<p>Je travaille dans l&#8217;équipe nommée Services. On travaille à la mise en
|
||
place de services web qui sont capables de tenir la charge, de
|
||
fonctionner de manière&nbsp;décentralisée.</p>
|
||
<p>Ce travail a plusieurs&nbsp;objectifs:</p>
|
||
<ul>
|
||
<li>Mettre à disposition des outils pour les développeurs, leur
|
||
permettant de créer des services de bonne qualité&nbsp;rapidement;</li>
|
||
<li>Permettre aux utilisateurs d&#8217;héberger eux mêmes leurs propres
|
||
serveurs s&#8217;ils le souhaitent, réduisant leur dépendance a des
|
||
services&nbsp;externes.</li>
|
||
<li>Écrire les services en question de telle manière que les
|
||
utilisateurs (vous !) puissent les utiliser sans avoir trop de
|
||
tracas&nbsp;:)</li>
|
||
</ul>
|
||
<p>Ça semble peu, mais j&#8217;aime ce boulot. Éthiquement et techniquement.
|
||
C&#8217;est ça, pour moi, la mission de Mozilla. Si vous avez des suggestions
|
||
sur ce qui pourrait être amélioré dans les services de Mozilla en termes
|
||
de protection de la vie privée, de décentralisation et de haute
|
||
disponibilité, vous savez vers qui vous tourner&nbsp;!</p>
|
||
<p>La liste des projets sur lesquels je travaille ou j&#8217;ai travaillé à
|
||
Mozilla pour&nbsp;l&#8217;instant:</p>
|
||
<ul>
|
||
<li><a href="https://github.com/mozilla-services/tokenserver">https://github.com/mozilla-services/tokenserver</a></li>
|
||
<li><a href="http://circus.io/">http://circus.io/</a></li>
|
||
<li><a href="http://powerhose.rtfd.org/">http://powerhose.rtfd.org/</a></li>
|
||
<li><a href="https://github.com/mozilla-services/server-aitc">https://github.com/mozilla-services/server-aitc</a></li>
|
||
<li><a href="http://cornice.readthedocs.org/en/latest/index.html">http://cornice.readthedocs.org/en/latest/index.html</a></li>
|
||
<li><a href="https://github.com/mozilla/PyBrowserID/">https://github.com/mozilla/PyBrowserID/</a></li>
|
||
<li><a href="http://chaussette.readthedocs.org/en/0.3/index.html">http://chaussette.readthedocs.org/en/0.3/index.html</a></li>
|
||
</ul></content><category term="journal"></category></entry><entry><title>Lifestyle</title><link href="https://blog.notmyidea.org/lifestyle.html" rel="alternate"></link><published>2012-05-11T00:00:00+02:00</published><updated>2012-05-11T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-05-11:/lifestyle.html</id><summary type="html">
|
||
<p>Eh beh, c&#8217;est pas aussi simple qu&#8217;il y parait de trouver un
|
||
environnement qui permette autant de travailler correctement et de ne
|
||
pas s&#8217;enfermer dans le&nbsp;boulot.</p>
|
||
<p>Surtout si comme moi vous cherchez à limiter vos déplacement, que vous
|
||
aimez vivre avec peu et cherchez à trouver …</p></summary><content type="html">
|
||
<p>Eh beh, c&#8217;est pas aussi simple qu&#8217;il y parait de trouver un
|
||
environnement qui permette autant de travailler correctement et de ne
|
||
pas s&#8217;enfermer dans le&nbsp;boulot.</p>
|
||
<p>Surtout si comme moi vous cherchez à limiter vos déplacement, que vous
|
||
aimez vivre avec peu et cherchez à trouver un équilibre entre une vie
|
||
connectée et une vie <em>réelle</em> (oui, celle avec des vrais gens qui ont
|
||
d&#8217;autres préoccupations que l&#8217;informatique !). Comment réussir à
|
||
trouver un juste milieu entre le geek inconditionnel et le bon vivant,
|
||
qui à du temps à consacrer à autre chose qu&#8217;à son travail&nbsp;?</p>
|
||
<h2 id="voyages">Voyages</h2>
|
||
<p>Un des premiers trucs que j&#8217;ai trouvé surprennant en arrivant à Mozilla,
|
||
c&#8217;est la fréquence des voyages que l&#8217;on peut être amené à avoir. Ah,
|
||
c&#8217;est pour la bonne cause, c&#8217;est tellement plus sympa d&#8217;avoir les
|
||
collègues à coté pour bosser, plutôt qu&#8217;à l&#8217;autre bout du monde. Mais
|
||
quand même, si je le voulais, entre les semaines de travail et les
|
||
conférences, je pourrais être tous les deux mois aux États-Unis&nbsp;!</p>
|
||
<p>Une aubaine, penserons certains. Voyager, c&#8217;est <em>cool</em> ! Bon, si on
|
||
mets de coté le cout écologique d&#8217;un voyage (nécessairement en avion),
|
||
la chose qui me dérange le plus c&#8217;est cette impression de venir pour
|
||
repartir. Voyager, c&#8217;est sympa, mais avoir le temps de prendre un rythme
|
||
de vie différent, de rencontrer des gens, de construire quelque chose,
|
||
ça me&nbsp;manque.</p>
|
||
<p>Donc je décline quand je n&#8217;en ai pas l&#8217;envie, tout simplement. Je loupe
|
||
des choses intéressantes (<a href="http://pycon.us">PyCon</a> à Santa Clara avait
|
||
vraiment l&#8217;air chouette !), mais ça me permet également d&#8217;avoir plus de
|
||
temps pour vivre là ou j&#8217;habite, pour construire quelque chose
|
||
localement. Et puis des évènements, il y en à tellement en France et en
|
||
Europe auquel je n&#8217;assiste pas que ça me fait mal au cœur d&#8217;aller à
|
||
l&#8217;autre bout du monde pour faire la même chose&nbsp;!</p>
|
||
<p>Bien sur, je serais amené à voyager. Et autant que faire se peut je le
|
||
ferais avec plaisir et je tenterais de rester un peu plus avant et après
|
||
sur place (plus question de faire un aller/retour en une semaine !),
|
||
question de me faire à l&#8217;atmosphère ! <a href="http://ziade.org">Tarek</a> est par
|
||
exemple resté un mois à San Francisco en janvier pour son dernier
|
||
séjour, alors pourquoi ne pas prendre exemple ? Tout de suite ça me
|
||
parles&nbsp;plus.</p>
|
||
<h2 id="et-quand-est-ce-quon-arrete">Et quand-est-ce qu&#8217;on arrête&nbsp;?</h2>
|
||
<p>Une autre chose assez difficile à gérer, c&#8217;est le&nbsp;temps.</p>
|
||
<p>J&#8217;ai vraiment une chance monstrueuse, celle de faire un travail qui me
|
||
plait, éthiquement et techniquement. Je pourrais y passer mes journées
|
||
et mes nuits que je n&#8217;aimerais pas moins ça (même si il m&#8217;arrive bien
|
||
sur de saturer&nbsp;!).</p>
|
||
<p>Mais j&#8217;ai aussi d&#8217;autres envies, qui signifient aussi passer du temps
|
||
hors-ligne, parce que bizarrement, c&#8217;est là que j&#8217;ai l&#8217;impression de
|
||
réfléchir le plus. Loin de ce surplus&nbsp;d&#8217;informations…</p>
|
||
<p>Facile à&nbsp;dire.</p>
|
||
<p>D&#8217;autant que quand il est possible de travailler depuis n&#8217;importe où, la
|
||
séparation physique entre le lieu de travail et le lieu de vie tends à
|
||
disparaitre assez facilement. Et sans séparation physique, il faut une
|
||
sacré motivation pour savoir quand commencer et quand&nbsp;s&#8217;arrêter.</p>
|
||
<p>J&#8217;essaye de me donner une règle simple: point trop n&#8217;en faut. Aucun
|
||
intérêt à rester travailler des heures durant sans s&#8217;arrêter, ou en
|
||
tout cas pas d&#8217;intérêt à le faire de manière trop régulière. Une journée
|
||
qui commence tôt (\~9h) me permet de me concentrer le matin (les
|
||
collègues californiens dorment) et d&#8217;avoir un rythme assez &#8220;normal&#8221;. Et
|
||
puis, avec ce soleil qui commence à inonder les terrasses, autant faire
|
||
autre chose que de rester enfermé à coder en fin d&#8217;après midi&nbsp;!</p>
|
||
<h2 id="surplus">Surplus</h2>
|
||
<p>Tiens, je parlais de surplus, nous y sommes. Que ça soit le surplus
|
||
d&#8217;informations ou le surplus d&#8217;objets, ça m&#8217;encombre ! Une journée,
|
||
pour ma part est faite de communications diverses, de code et de
|
||
lectures (se tenir au courant de ce qui se passe dans le monde du
|
||
logiciel n&#8217;est pas une tâche des plus facile, et qui peut facilement
|
||
prendre énormément de&nbsp;temps).</p>
|
||
<p>Je me demande si je ne devrais pas aspirer à la frugalité de ce coté là
|
||
également. Je reçois des mails toute la journée, et mon aggrégateur
|
||
rss/atom se remplit également très vite. Mais je n&#8217;ai aucunement besoin
|
||
d&#8217;avoir toutes ces informations dans l&#8217;heure, et de les vérifier de
|
||
manière fréquente. De la même manière, j&#8217;ai simplement arrêté de lire
|
||
mes flux&nbsp;rss.</p>
|
||
<p>Quelques (longues) fois dans la semaine semblent suffire et me
|
||
permettent de réussir à rester&nbsp;concentrer.</p>
|
||
<h2 id="resolutions">Résolutions</h2>
|
||
<p>Soyons fous, tentons quelque chose de nouveau, c&#8217;est le printemps ! Pas
|
||
de communication dans la matinée, je n&#8217;en ai probablement pas besoin,
|
||
sauf cas extrêmes. Le matin, c&#8217;est pour se concentrer sur le travail à&nbsp;faire.</p>
|
||
<p>Une fois les mails du matin dépilés (à 9h30), pas la peine de garder un
|
||
œil sur ma boite mail, j&#8217;irais y faire un tour en début et en fin
|
||
d&#8217;après&nbsp;midi.</p>
|
||
<p>Je pense même à débrancher internet, pour éviter les interactions et
|
||
pour me concentrer, mais j&#8217;ai comme l&#8217;impression que c&#8217;est un peu trop
|
||
abrupt comme&nbsp;approche.</p>
|
||
<p>Aussi, définir en début de journée la liste des choses prévues, et
|
||
revenir dessus jour après jour me permettra surement d&#8217;avoir un aperçu
|
||
un peu plus global du travail&nbsp;accompli.</p>
|
||
<p>L&#8217;avenir dira si tout ça fonctionne&nbsp;:-)</p></content><category term="journal"></category></entry><entry><title>Refactoring Cornice</title><link href="https://blog.notmyidea.org/refactoring-cornice.html" rel="alternate"></link><published>2012-05-01T00:00:00+02:00</published><updated>2012-05-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-05-01:/refactoring-cornice.html</id><summary type="html">
|
||
<p>After working for a while with <a href="http://cornice.readthedocs.com">Cornice</a>
|
||
to define our APIs at <a href="http://docs.services.mozilla.com">Services</a>, it
|
||
turned out that the current implementation wasn&#8217;t flexible enough to
|
||
allow us to do what we wanted to&nbsp;do.</p>
|
||
<p>Cornice started as a toolkit on top of the
|
||
<a href="http://docs.pylonsproject.org/en/latest/docs/pyramid.html">pyramid</a>
|
||
routing system, allowing to register services …</p></summary><content type="html">
|
||
<p>After working for a while with <a href="http://cornice.readthedocs.com">Cornice</a>
|
||
to define our APIs at <a href="http://docs.services.mozilla.com">Services</a>, it
|
||
turned out that the current implementation wasn&#8217;t flexible enough to
|
||
allow us to do what we wanted to&nbsp;do.</p>
|
||
<p>Cornice started as a toolkit on top of the
|
||
<a href="http://docs.pylonsproject.org/en/latest/docs/pyramid.html">pyramid</a>
|
||
routing system, allowing to register services in a simpler way. Then we
|
||
added some niceties such as the ability to automatically generate the
|
||
services documentation or returning the correct <span class="caps">HTTP</span> headers <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">as defined
|
||
by the <span class="caps">HTTP</span>
|
||
specification</a>
|
||
without the need from the developer to deal with them nor to know&nbsp;them.</p>
|
||
<p>If you&#8217;re not familiar with Cornice, here is how you define a simple
|
||
service with&nbsp;it:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">from</span> <span class="nn">cornice.service</span> <span class="kn">import</span> <span class="n">Service</span>
|
||
<span class="n">bar</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s2">&quot;/bar&quot;</span><span class="p">)</span>
|
||
|
||
<span class="nd">@bar</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">validators</span><span class="o">=</span><span class="n">validators</span><span class="p">,</span> <span class="n">accept</span><span class="o">=</span><span class="s1">&#39;application/json&#39;</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">get_drink</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="c1"># do something with the request (with moderation).</span>
|
||
</code></pre></div>
|
||
|
||
<p>This external <span class="caps">API</span> is quite cool, as it allows to do a bunch of things
|
||
quite easily. For instance, we&#8217;ve written our
|
||
<a href="https://github.com/mozilla-services/tokenserver">token-server</a> code on
|
||
top of this in a&nbsp;blast.</p>
|
||
<h2 id="the-burden">The&nbsp;burden</h2>
|
||
<p>The problem with this was that we were mixing internally the service
|
||
description logic with the route registration one. The way we were doing
|
||
this was via an extensive use of decorators&nbsp;internally.</p>
|
||
<p>The <span class="caps">API</span> of the cornice.service.Service class was as following
|
||
(simplified so you can get the gist of&nbsp;it).</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Service</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">service_kwargs</span><span class="p">):</span>
|
||
<span class="c1"># some information, such as the colander schemas (for validation),</span>
|
||
<span class="c1"># the defined methods that had been registered for this service and</span>
|
||
<span class="c1"># some other things were registered as instance variables.</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">schemas</span> <span class="o">=</span> <span class="n">service_kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">schema</span><span class="s1">&#39;, None)</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">defined_methods</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">definitions</span> <span class="o">=</span> <span class="p">[]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">api</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">view_kwargs</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;This method is a decorator that is being used by some alias</span>
|
||
<span class="sd"> methods.</span>
|
||
<span class="sd"> &quot;&quot;&quot;</span>
|
||
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">view</span><span class="p">):</span>
|
||
<span class="c1"># all the logic goes here. And when I mean all the logic, I</span>
|
||
<span class="c1"># mean it.</span>
|
||
<span class="c1"># 1. we are registering a callback to the pyramid routing</span>
|
||
<span class="c1"># system so it gets called whenever the module using the</span>
|
||
<span class="c1"># decorator is used.</span>
|
||
<span class="c1"># 2. we are transforming the passed arguments so they conform</span>
|
||
<span class="c1"># to what is expected by the pyramid routing system.</span>
|
||
<span class="c1"># 3. We are storing some of the passed arguments into the</span>
|
||
<span class="c1"># object so we can retrieve them later on.</span>
|
||
<span class="c1"># 4. Also, we are transforming the passed view before</span>
|
||
<span class="c1"># registering it in the pyramid routing system so that it</span>
|
||
<span class="c1"># can do what Cornice wants it to do (checking some rules,</span>
|
||
<span class="c1"># applying validators and filters etc.</span>
|
||
<span class="k">return</span> <span class="n">wrapper</span>
|
||
|
||
<span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;A shortcut of the api decorator&quot;&quot;&quot;</span>
|
||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">api</span><span class="p">(</span><span class="n">request_method</span><span class="o">=</span><span class="s2">&quot;GET&quot;</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>I encourage you to go read <a href="https://github.com/mozilla-services/cornice/blob/4e0392a2ae137b6a11690459bcafd7325e86fa9e/cornice/service.py#L44">the entire
|
||
file</a>.
|
||
on github so you can get a better opinion on how all of this was&nbsp;done.</p>
|
||
<p>A bunch of things are&nbsp;wrong:</p>
|
||
<ul>
|
||
<li>first, we are not separating the description logic from the
|
||
registration one. This causes problems when we need to access the
|
||
parameters passed to the service, because the parameters you get are
|
||
not exactly the ones you passed but the ones that the pyramid
|
||
routing system is expecting. For instance, if you want to get the
|
||
view get_drink, you will instead get a decorator which contains
|
||
this&nbsp;view.</li>
|
||
<li>second, we are using decorators as APIs we expose. Even if
|
||
decorators are good as shortcuts, they shouldn&#8217;t be the default way
|
||
to deal with an <span class="caps">API</span>. A good example of this is <a href="https://github.com/mozilla-services/cornice/blob/4e0392a2ae137b6a11690459bcafd7325e86fa9e/cornice/resource.py#L56">how the resource
|
||
module consumes this
|
||
<span class="caps">API</span></a>.
|
||
This is quite hard to&nbsp;follow.</li>
|
||
<li>Third, in the api method, a bunch of things are done regarding
|
||
inheritance of parameters that are passed to the service or to its
|
||
decorator methods. This leaves you with a really hard to follow path
|
||
when it comes to add new parameters to your <span class="caps">API</span>.</li>
|
||
</ul>
|
||
<h2 id="how-do-we-improve-this">How do we improve&nbsp;this?</h2>
|
||
<p>Python is great because it allows you to refactor things in an easy way.
|
||
What I did isn&#8217;t breaking our APIs, but make things way simpler to
|
||
hack-on. One example is that it allowed me to add features that we
|
||
wanted to bring to Cornice really quickly (a matter of minutes), without
|
||
touching the <span class="caps">API</span> that&nbsp;much.</p>
|
||
<p>Here is the gist of the new&nbsp;architecture:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="k">class</span> <span class="nc">Service</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||
<span class="c1"># we define class-level variables that will be the default values for</span>
|
||
<span class="c1"># this service. This makes things more extensible than it was before.</span>
|
||
<span class="n">renderer</span> <span class="o">=</span> <span class="s1">&#39;simplejson&#39;</span>
|
||
<span class="n">default_validators</span> <span class="o">=</span> <span class="n">DEFAULT_VALIDATORS</span>
|
||
<span class="n">default_filters</span> <span class="o">=</span> <span class="n">DEFAULT_FILTERS</span>
|
||
|
||
<span class="c1"># we also have some class-level parameters that are useful to know</span>
|
||
<span class="c1"># which parameters are supposed to be lists (and so converted as such)</span>
|
||
<span class="c1"># or which are mandatory.</span>
|
||
<span class="n">mandatory_arguments</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;renderer&#39;</span><span class="p">,)</span>
|
||
<span class="n">list_arguments</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;validators&#39;</span><span class="p">,</span> <span class="s1">&#39;filters&#39;</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
|
||
<span class="c1"># setup name, path and description as instance variables</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="n">path</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">description</span> <span class="o">=</span> <span class="n">description</span>
|
||
|
||
<span class="c1"># convert the arguments passed to something we want to store</span>
|
||
<span class="c1"># and then store them as attributes of the instance (because they</span>
|
||
<span class="c1"># were passed to the constructor</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">arguments</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_arguments</span><span class="p">(</span><span class="n">kw</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">arguments</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
||
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
||
|
||
<span class="c1"># we keep having the defined_methods tuple and the list of</span>
|
||
<span class="c1"># definitions that are done for this service</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">defined_methods</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">definitions</span> <span class="o">=</span> <span class="p">[]</span>
|
||
|
||
<span class="k">def</span> <span class="nf">get_arguments</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conf</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Returns a dict of arguments. It does all the conversions for</span>
|
||
<span class="sd"> you, and uses the information that were defined at the instance</span>
|
||
<span class="sd"> level as fallbacks.</span>
|
||
<span class="sd"> &quot;&quot;&quot;</span>
|
||
|
||
<span class="k">def</span> <span class="nf">add_view</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">view</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add a view to this service.&quot;&quot;&quot;</span>
|
||
<span class="c1"># this is really simple and looks a lot like this</span>
|
||
<span class="n">method</span> <span class="o">=</span> <span class="n">method</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">definitions</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">method</span><span class="p">,</span> <span class="n">view</span><span class="p">,</span> <span class="n">args</span><span class="p">))</span>
|
||
<span class="k">if</span> <span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">defined_methods</span><span class="p">:</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">defined_methods</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">method</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">&quot;&quot;&quot;This is only another interface to the add_view method, exposing a</span>
|
||
<span class="sd"> decorator interface&quot;&quot;&quot;</span>
|
||
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">view</span><span class="p">):</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">add_view</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="n">view</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">view</span>
|
||
<span class="k">return</span> <span class="n">wrapper</span>
|
||
</code></pre></div>
|
||
|
||
<p>So, the service is now only storing the information that&#8217;s passed to it
|
||
and nothing more. No more route registration logic goes here. Instead, I
|
||
added this as another feature, even in a different module. The function
|
||
is named register_service_views and has the following&nbsp;signature:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">register_service_views</span><span class="p">(</span><span class="n">config</span><span class="p">,</span> <span class="n">service</span><span class="p">)</span>
|
||
</code></pre></div>
|
||
|
||
<p>To sum up, here are the changes I&nbsp;made:</p>
|
||
<ol>
|
||
<li>Service description is now separated from the route&nbsp;registration.</li>
|
||
<li>cornice.service.Service now provides a hook_view method, which is
|
||
not a decorator. decorators are still present but they are optional
|
||
(you don&#8217;t need to use them if you don&#8217;t want&nbsp;to).</li>
|
||
<li>Everything has been decoupled as much as possible, meaning that you
|
||
really can use the Service class as a container of information about
|
||
the services you are describing. This is especially useful when
|
||
generating&nbsp;documentation.</li>
|
||
</ol>
|
||
<p>As a result, it is now possible to use Cornice with other frameworks. It
|
||
means that you can stick with the service description but plug any other
|
||
framework on top of it. cornice.services.Service is now only a
|
||
description tool. To register routes, one would need to read the
|
||
information contained into this service and inject the right parameters
|
||
into their preferred routing&nbsp;system.</p>
|
||
<p>However, no integration with other frameworks is done at the moment even
|
||
if the design allows&nbsp;it.</p>
|
||
<p>The same way, the sphinx description layer is now only a consumer of
|
||
this service description tool: it looks at what&#8217;s described and build-up
|
||
the documentation from&nbsp;it.</p>
|
||
<p>The resulting branch is not merged yet. Still, you can <a href="https://github.com/mozilla-services/cornice/tree/refactor-the-world">have a look at
|
||
it</a>.</p>
|
||
<p>Any suggestions are of course welcome&nbsp;:-)</p></content><category term="code"></category></entry><entry><title>Bidouille</title><link href="https://blog.notmyidea.org/bidouille.html" rel="alternate"></link><published>2012-04-30T00:00:00+02:00</published><updated>2012-04-30T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-04-30:/bidouille.html</id><summary type="html">
|
||
<p>Bidouille bidouille&nbsp;bidouille.</p>
|
||
<p>Je pense que je suis un bidouilleur logiciel: j&#8217;aime bien aller
|
||
farfouiller dans le code pour comprendre comment tel ou tel programme
|
||
fonctionne (ou trop souvent comment il ne fonctionne pas !), faire des
|
||
petites modifications, tester, modifier, re-tester, tout casser, réparer&nbsp;…</p>
|
||
<p>Et cette bidouille, cette envie …</p></summary><content type="html">
|
||
<p>Bidouille bidouille&nbsp;bidouille.</p>
|
||
<p>Je pense que je suis un bidouilleur logiciel: j&#8217;aime bien aller
|
||
farfouiller dans le code pour comprendre comment tel ou tel programme
|
||
fonctionne (ou trop souvent comment il ne fonctionne pas !), faire des
|
||
petites modifications, tester, modifier, re-tester, tout casser, réparer&nbsp;…</p>
|
||
<p>Et cette bidouille, cette envie de comprendre comment les choses
|
||
fonctionnent, et depuis peu cette envie de mettre en pratique ces
|
||
connaissances dépasse la bidouille logicielle. J&#8217;ai passé une grosse
|
||
partie de mon week-end à Main d&#8217;Œuvre, où l&#8217;association <a href="http://www.underconstruction.fr">Under
|
||
Construction</a> faisait se rencontrer le
|
||
milieu de l&#8217;éducation populaire et le milieu de la&nbsp;bidouille.</p>
|
||
<p>Forcement, ni une ni deux, je saute dans le bateau en marche et, n&#8217;étant
|
||
ni un très grand bidouilleur ni un très grand animateur, j&#8217;en ressort
|
||
enrichi de toutes ces rencontres, de tous ces préjugés qui tombent, et
|
||
de quelques découvertes bluffantes, des idées plein la&nbsp;tête.</p>
|
||
<p>J&#8217;avais entendu parler des &#8220;<a href="http://www.reprap.org">rep-raps</a>&#8220;, des
|
||
imprimantes en 3 dimensions capables de produire des pièces en plastique
|
||
mais je n&#8217;avais jamais eu l&#8217;occasion de voir le bousin en vrai. Et c&#8217;est
|
||
impressionnant. Vraiment. (&#8220;Bienvenue dans le 21ème siècle&nbsp;!&#8221;)</p>
|
||
<p>Ça laisse énormément à penser autour des questions d&#8217;émancipation
|
||
technologique, et de non dépendance envers les constructeurs, dans le
|
||
milieu de l&#8217;électro-ménager, par exemple. &#8220;Ah tiens, cette pièce est
|
||
cassée, je vais aller utiliser la rep-rap du coin pour me la fabriquer&#8221;.
|
||
Et hop, on mets fin à tout un cycle d&#8217;obsolescence&nbsp;programmée…</p>
|
||
<p>Mais au delà du défi technique et technologique, j&#8217;ai pu refaire un
|
||
petit peu d&#8217;électronique, et découvrir que j&#8217;y prends vraiment gout
|
||
rapidement. Il y a bien évidemment un coté très ludique (la led s&#8217;allume
|
||
quand on la branche), mais il y a surtout cette notion de <span class="caps">DIY</span> (Do It
|
||
Yourself) sous jacente: une fois que je sais comment ça fonctionne, je
|
||
peux vraiment faire des choses utiles de mes 10 doigts, réparer des
|
||
petits objets, bidouiller ceux existants&nbsp;etc.</p>
|
||
<p>De la récupération de composants on essaye de voir ce qu&#8217;on peut faire,
|
||
on a terminé par faire un &#8220;vibro-bot&#8221;, un vibreur de téléphone portable
|
||
monté sur une tête de brosse à dents, faisant donc avancer cette&nbsp;dernière.</p>
|
||
<p>C&#8217;est pour s&#8217;amuser, c&#8217;est pas sérieux ! Pour autant, les concepts de
|
||
l&#8217;électricité sont appris et je me retrouve avec cette envie de
|
||
comprendre un peu plus ce monde de l&#8217;électronique qui, je m&#8217;en rends
|
||
compte, m&#8217;échappe encore complètement. De l&#8217;éducation à la bidouille&nbsp;!</p>
|
||
<p>Allez, demain c&#8217;est fer à souder, piles, leds, interrupteurs, potars et
|
||
c&#8217;est parti&nbsp;!</p></content><category term="journal"></category></entry><entry><title>Djangocong 2012</title><link href="https://blog.notmyidea.org/djangocong-2012.html" rel="alternate"></link><published>2012-04-16T00:00:00+02:00</published><updated>2012-04-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-04-16:/djangocong-2012.html</id><summary type="html">
|
||
<p>Ce week-end, c&#8217;était <a href="http://rencontres.django-fr.org">djangocong</a>, une
|
||
conférence autour de <a href="http://djangoproject.org">django</a>, de
|
||
<a href="http://python.org">python</a> et du web, qui avait lieu dans le sud, à
|
||
Carnon-plage, à quelques kilomètres de Montpellier la&nbsp;belle.</p>
|
||
<p>J&#8217;ai vraiment apprécié les trois jours passés avec cette bande de geeks.
|
||
Je m&#8217;attendais à des <em>nerds</em>, j …</p></summary><content type="html">
|
||
<p>Ce week-end, c&#8217;était <a href="http://rencontres.django-fr.org">djangocong</a>, une
|
||
conférence autour de <a href="http://djangoproject.org">django</a>, de
|
||
<a href="http://python.org">python</a> et du web, qui avait lieu dans le sud, à
|
||
Carnon-plage, à quelques kilomètres de Montpellier la&nbsp;belle.</p>
|
||
<p>J&#8217;ai vraiment apprécié les trois jours passés avec cette bande de geeks.
|
||
Je m&#8217;attendais à des <em>nerds</em>, j&#8217;y ai trouvé une qualité d&#8217;écoute, des
|
||
personnes qui partagent des valeurs qui leur sont chères, mais qui ne
|
||
limitent pas leurs discussions à du technique. Eeeh ouais, encore un
|
||
préjugé qui tombe, tiens&nbsp;:)</p>
|
||
<p>En tant que <em>hackers</em>, on a le moyen de créer des outils qui sont utiles
|
||
à tous, et qui peuvent être utiles pour favoriser la collaboration et la
|
||
mise en commun des données. J&#8217;ai eu l&#8217;occasion de discuter de projets
|
||
tournant autour de l&#8217;entraide, que ça soit pour mettre en lien des
|
||
associations d&#8217;économie sociale et solidaire (<span class="caps">ESS</span>) ou simplement pour
|
||
que les populations <em>non tech</em> <a href="http://blog.notmyidea.org/quels-usages-pour-linformatique-fr.html">puissent utiliser toute la puissance de
|
||
l&#8217;outil qu&#8217;est le
|
||
web</a>.</p>
|
||
<p>Au niveau du format des conférences, je ne savais pas trop à quoi
|
||
m&#8217;attendre, au vu des échos de l&#8217;an dernier, mais c&#8217;était adapté: des
|
||
mini-confs de 12mn le samedi matin + début d&#8217;aprem, en mode no-wifi pour
|
||
récupérer une qualité d&#8217;écoute. Et contrairement à mes attentes, ce
|
||
n&#8217;est pas trop court. Pas mal de retours d&#8217;expérience pour le coup, et
|
||
une matinée pas vraiment techniques, mais ça pose le décor et permet de
|
||
savoir qui fait&nbsp;quoi.</p>
|
||
<p>Parmi l&#8217;ensemble des conférences du matin, je retiens principalement
|
||
celle de Mathieu Leplatre, &#8220;des cartes d&#8217;un autre monde&#8221;, qui m&#8217;a
|
||
réellement bluffée quand à la facilité de créer des cartes avec
|
||
<a href="http://mapbox.com/tilemill/">TileMill</a>, et qui me pousse à reconsidérer
|
||
le fait que &#8220;la carto, c&#8217;est compliqué&#8221;. <a href="https://www.youtube.com/watch?v=7NPQo54NbJ8">La vidéo est (déja !)
|
||
disponible en ligne</a>, je
|
||
vous invite à la regarder (c&#8217;est une 15aine de minutes) pour vous faire
|
||
un avis&nbsp;;)</p>
|
||
<p>Une fois les conf passées, ça reste très intéressant, voire plus: il
|
||
reste un jour et demi pour discuter avec les autres présents. On a pu se
|
||
retrouver avec Mathieu pour discuter de &#8220;notre&#8221; projet <a href="http://blog.notmyidea.org/carto-forms-fr.html">&#8220;carto
|
||
forms&#8221;</a>, qui à finalement
|
||
pu se redéfinir un peu plus et donner naissance à un
|
||
<a href="https://github.com/spiral-project/daybed/blob/master/README.rst"><span class="caps">README</span></a>.
|
||
On en à profité pour lui choisir un nouveau nom: &#8220;daybed&#8221;, en référence
|
||
à&nbsp;couchdb.</p>
|
||
<p>Ça devrait se transformer en code d&#8217;ici peu. La curiosité aidant, on a
|
||
pu discuter du projet avec d&#8217;autres personnes et affiner les attentes de
|
||
chacun pour finalement arriver à quelque chose d&#8217;assez&nbsp;sympathique.</p>
|
||
<p>J&#8217;ai aussi pu me rendre compte que pas mal de monde utilise
|
||
<a href="http://pelican.notmyidea.org">pelican</a>, le bout de code que j&#8217;ai codé
|
||
pour générer ce blog, et avoir des retours utiles ! Probablement des
|
||
réflexions à venir sur comment éviter qu&#8217;un projet open-source ne
|
||
devienne chronophage, et sur comment réussir à garder une qualité dans
|
||
le code source tout en ne froissant pas les&nbsp;contributeurs.</p>
|
||
<p>Bien évidemment, c&#8217;était aussi l&#8217;occaz de rencontrer des gens qu&#8217;on ne
|
||
voir que sur les inter-nets, et de discuter un brin de tout ce qui fait
|
||
que notre monde est chouette et moins&nbsp;chouette.</p>
|
||
<p>Entres autres faits notoires, JMad a perdu au baby-foot face à Exirel,
|
||
même en m&#8217;ayant à ses cotés pour le déconcentrer (et je suis un joueur
|
||
d&#8217;un autre monde - en d&#8217;autres termes, je suis nul), David`bgk ne s&#8217;est
|
||
pas levé pour aller courir le dimanche matin (il avait dit 5 heures!),
|
||
Les suisses ont essayé de me convertir à coup d&#8217;abricotine, j&#8217;ai perdu
|
||
au skulls-n-roses en quelques tours et on a allumé un feu chez Stéphane
|
||
le dimanche soir (oui oui, à montpellier, mi avril, je vous le dis
|
||
qu&#8217;ils mentent avec leur soit disant&nbsp;soleil).</p>
|
||
<p>Et c&#8217;est sans parler de <a href="http://jehaisleprintemps.net/blog/fr/2012/04/15/j-ecris-ton-nom/">la
|
||
brasucade</a>&nbsp;…</p>
|
||
<p>Bref, vivement la prochaine (et allez, cette fois ci je ferais une
|
||
présentation&nbsp;!)</p></content><category term="code"></category></entry><entry><title>Génération de formulaires, geolocalisés ?</title><link href="https://blog.notmyidea.org/generation-de-formulaires-geolocalises.html" rel="alternate"></link><published>2012-04-02T00:00:00+02:00</published><updated>2012-04-02T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-04-02:/generation-de-formulaires-geolocalises.html</id><summary type="html">
|
||
<p>On a un plan. Un &#8220;truc de&nbsp;ouf&#8221;.</p>
|
||
<p>À plusieurs reprises, des amis m&#8217;ont demandé de leur coder la même
|
||
chose, à quelques détails près: une page web avec un formulaire qui
|
||
permettrait de soumettre des informations géographiques, lié à une carte
|
||
et des manières de filtrer&nbsp;l&#8217;information …</p></summary><content type="html">
|
||
<p>On a un plan. Un &#8220;truc de&nbsp;ouf&#8221;.</p>
|
||
<p>À plusieurs reprises, des amis m&#8217;ont demandé de leur coder la même
|
||
chose, à quelques détails près: une page web avec un formulaire qui
|
||
permettrait de soumettre des informations géographiques, lié à une carte
|
||
et des manières de filtrer&nbsp;l&#8217;information.</p>
|
||
<p>L&#8217;idée fait son bout de chemin, et je commence à penser qu&#8217;on peut même
|
||
avoir quelque chose de vraiment flexible et utile. J&#8217;ai nommé le projet
|
||
<em>carto-forms</em> pour l&#8217;instant (mais c&#8217;est uniquement un nom de&nbsp;code).</p>
|
||
<p>Pour résumer: et si on avait un moyen de construire des formulaires, un
|
||
peu comme Google forms, mais avec des informations géographiques en&nbsp;plus?</p>
|
||
<p>Si vous ne connaissez pas Google forms, il s&#8217;agit d&#8217;une interface simple
|
||
d&#8217;utilisation pour générer des formulaires et récupérer des informations
|
||
depuis ces&nbsp;derniers.</p>
|
||
<p>Google forms est un super outil mais à mon avis manque deux choses
|
||
importantes: premièrement, il s&#8217;agit d&#8217;un outil propriétaire (oui, on
|
||
peut aussi dire privateur) et il n&#8217;est donc pas possible de le hacker un
|
||
peu pour le faire devenir ce qu&#8217;on souhaite, ni l&#8217;installer sur notre
|
||
propre serveur. Deuxièmement, il ne sait pas vraiment fonctionner avec
|
||
des informations géographiques, et il n&#8217;y à pas d&#8217;autre moyen de filtrer
|
||
les informations que l&#8217;utilisation de leur système de feuilles de&nbsp;calcul.</p>
|
||
<p>Après avoir réfléchi un petit peu à ça, j&#8217;ai contacté
|
||
<a href="http://blog.mathieu-leplatre.info/">Mathieu</a> et les anciens collègues
|
||
de chez <a href="http://makina-corpus.com">Makina Corpus</a>, puisque les projets
|
||
libres à base de carto sont à même de les&nbsp;intéresser.</p>
|
||
<p>Imaginez le cas&nbsp;suivant:</p>
|
||
<ol>
|
||
<li>Dans une &#8220;mapping party&#8221;, on choisit un sujet particulier à
|
||
cartographier et on design un formulaire (liste des champs (tags) a
|
||
remplir + description + le type d&#8217;information)&nbsp;;</li>
|
||
<li>Sur place, les utilisateurs remplissent les champs du formulaire
|
||
avec ce qu&#8217;ils voient. Les champs géolocalisés peuvent être remplis
|
||
automatiquement avec la géolocalisation du téléphone&nbsp;;</li>
|
||
<li>À la fin de la journée, il est possible de voir une carte des
|
||
contributions, avec le formulaire choisi&nbsp;;</li>
|
||
<li>Un script peut importer les résultats et les publier vers&nbsp;OpenStreetMap.</li>
|
||
</ol>
|
||
<h2 id="quelques-cas-dutilisation">Quelques cas&nbsp;d&#8217;utilisation</h2>
|
||
<p>J&#8217;arrive à imaginer différents cas d&#8217;utilisation pour cet outil. Le
|
||
premier est celui que j&#8217;ai approximativement décrit plus haut: la
|
||
génération de cartes de manière collaborative, avec des filtres à
|
||
facettes. Voici un flux d&#8217;utilisation&nbsp;général:</p>
|
||
<ul>
|
||
<li>
|
||
<p>Un &#8220;administrateur&#8221; se rend sur le site web et crée un nouveau
|
||
formulaire pour l&#8217;ensemble des évènements alternatifs. Il crée les
|
||
champs&nbsp;suivants:</p>
|
||
<ul>
|
||
<li>Nom: le champ qui contient le nom de&nbsp;l&#8217;évènement.</li>
|
||
<li>Catégorie: la catégorie de l&#8217;évènement (marche, concert,
|
||
manifestation…). Il peut s&#8217;agir d&#8217;un champ à multiples&nbsp;occurrences.</li>
|
||
<li>Le lieu de l&#8217;évènement. Celui-ci peut être donné soit par une
|
||
adresse soit en sélectionnant un point sur une&nbsp;carte.</li>
|
||
<li>Date: la date de l&#8217;évènement (un &#8220;date picker&#8221; peut permettre
|
||
cela&nbsp;facilement)</li>
|
||
</ul>
|
||
<p>Chaque champ dans le formulaire a des informations sémantiques
|
||
associées (oui/non, multiple sélection, date, heure, champ géocodé,
|
||
sélection carto,&nbsp;etc.)</p>
|
||
</li>
|
||
<li>
|
||
<p>Une fois terminé, le formulaire est généré et une <span class="caps">URL</span> permet d&#8217;y
|
||
accéder. (par exemple <a href="http://forms.notmyidea.org/alternatives">http://forms.notmyidea.org/alternatives</a>).</p>
|
||
</li>
|
||
<li>
|
||
<p>Une <span class="caps">API</span> <span class="caps">REST</span> permet à d&#8217;autres applications d&#8217;accéder aux
|
||
informations et d&#8217;en ajouter / modifier de&nbsp;nouvelles.</p>
|
||
</li>
|
||
<li>
|
||
<p>Il est maintenant possible de donner l&#8217;<span class="caps">URL</span> à qui voudra en faire bon
|
||
usage. N&#8217;importe qui peut ajouter des informations. On peut
|
||
également imaginer une manière de modérer les modifications si
|
||
besoin&nbsp;est.</p>
|
||
</li>
|
||
<li>
|
||
<p>Bien sur, la dernière phase est la plus intéressante: il est
|
||
possible de filtrer les informations par lieu, catégorie ou date, le
|
||
tout soit via une <span class="caps">API</span> <span class="caps">REST</span>, soit via une jolie carte et quelques
|
||
contrôles bien placés, dans le&nbsp;navigateur.</p>
|
||
</li>
|
||
</ul>
|
||
<p>Vous avez dû remarquer que le processus de création d&#8217;un formulaire est
|
||
volontairement très simple. L&#8217;idée est que n&#8217;importe qui puisse créer
|
||
des cartes facilement, en quelques clics. Si une <span class="caps">API</span> bien pensée suit,
|
||
on peut imaginer faire de la validation coté serveur et même faire des
|
||
applications pour téléphone assez&nbsp;simplement.</p>
|
||
<p>Pour aller un peu plus loin, si on arrive à penser un format de
|
||
description pour le formulaire, il sera possible de construire les
|
||
formulaires de manière automatisée sur différentes plateformes et
|
||
également sur des clients&nbsp;génériques.</p>
|
||
<p>On imagine pas mal d&#8217;exemples pour ce projet: des points de recyclage,
|
||
les endroits accessibles (pour fauteuils roulants etc.), identification
|
||
des arbres, bons coins à champignons, recensement des espèces en voie de
|
||
disparition (l&#8217;aigle de Bonelli est actuellement suivi en utilisant une
|
||
feuille de calcul partagée !), suivi des espèces dangereuses (le frelon
|
||
asiatique par exemple), cartographier les points d&#8217;affichage
|
||
publicitaires, participation citoyenne (graffitis, nids de poule, voir
|
||
<a href="http://fixmystreet.ca">http://fixmystreet.ca</a>), geocaching, trajectoires (randonnées,
|
||
coureurs,&nbsp;cyclistes)…</p>
|
||
<p>Voici quelques exemples où ce projet pourrait être utile (la liste n&#8217;est
|
||
pas&nbsp;exhaustive):</p>
|
||
<h3 id="un-backend-sig-simple-a-utiliser">Un backend <span class="caps">SIG</span> simple à&nbsp;utiliser</h3>
|
||
<p>Disons que vous êtes développeur mobile. Vous ne voulez pas vous
|
||
encombrer avec PostGIS ou écrire du code spécifique pour récupérer et
|
||
insérer des données <span class="caps">SIG</span>! Vous avez besoin de <em>Carto-Forms</em>! Une <span class="caps">API</span>
|
||
simple vous aide à penser vos modèles et vos formulaires, et cette même
|
||
<span class="caps">API</span> vous permet d&#8217;insérer et de récupérer des données. Vous pouvez vous
|
||
concentrer sur votre application et non pas sur la manière dont les
|
||
données géographiques sont stockées et&nbsp;gérées.</p>
|
||
<p>En d&#8217;autres termes, vous faites une distinction entre le stockage des
|
||
informations et leur&nbsp;affichage.</p>
|
||
<p>Si vous êtes un développeur django, plomino, drupal etc. vous pouvez
|
||
développer un module pour &#8220;plugger&#8221; vos modèles et votre interface
|
||
utilisateur avec celle de <em>Carto-Forms</em>. De cette manière, il est
|
||
possible d&#8217;exposer les formulaires aux utilisateurs de vos backoffices.
|
||
De la même manière, il est possible d&#8217;écrire des widgets qui consomment
|
||
des données et les affichent (en utilisant par exemple une bibliothèque
|
||
javascript de&nbsp;webmapping).</p>
|
||
<h3 id="un-outil-de-visualisation">Un outil de&nbsp;visualisation</h3>
|
||
<p>Puisque les données peuvent être proposées de manière automatisée en
|
||
utilisant l&#8217;<span class="caps">API</span>, vous pouvez utiliser la page de résultat de Carto-forms
|
||
comme un outil de&nbsp;visualisation.</p>
|
||
<p>Il est possible d&#8217;explorer mon jeu de données en utilisant des filtres
|
||
sur chacun des champs. La recherche à facettes peut être une idée pour
|
||
faciliter ce filtrage. Une carte affiche le résultat. Vous avez
|
||
l&#8217;impressoin d&#8217;être en face d&#8217;un système d&#8217;aide à la décision&nbsp;!</p>
|
||
<p>Évidemment, il est possible de télécharger les données brutes (geojson,
|
||
xml). Idéalement, le mieux serait d&#8217;obtenir ces données filtrées
|
||
directement depuis une <span class="caps">API</span> Web, et un lien permet de partager la page
|
||
avec l&#8217;état des filtres et le niveau de zoom / la localisation de la&nbsp;carte.</p>
|
||
<h3 id="un-service-generique-pour-gerer-les-formulaires">Un service générique pour gérer les&nbsp;formulaires</h3>
|
||
<p>Si vous souhaitez générer un fichier de configuration (ou ce que vous
|
||
voulez, messages emails, …) vous aurez besoin d&#8217;un formulaire et d&#8217;un
|
||
template pour injecter les données proposées par les utilisateurs et
|
||
récupérer un&nbsp;résultat.</p>
|
||
<p>Un service de gestion des formulaires pourrait être utile pour créer des
|
||
formulaires de manière automatique et récupérer les données &#8220;nettoyées&#8221;
|
||
et&nbsp;&#8220;validées&#8221;.</p>
|
||
<p>On peut imaginer par exemple l&#8217;utilisation d&#8217;un système de templates
|
||
externe reposant sur <em>carto-forms</em>. Celui-ci &#8220;parserait&#8221; le contenu des
|
||
templates et pourrait le lier aux informations ajoutées par les
|
||
utilisateurs via un&nbsp;formulaire.</p>
|
||
<p>Pour ce cas particulier, il n&#8217;y a pas besoin d&#8217;informations
|
||
géographiques (<span class="caps">SIG</span>). Il s&#8217;agit quasiment du service proposé
|
||
actuellement par Google&nbsp;forms.</p>
|
||
<h2 id="ca-nexiste-pas-deja-tout-ca">Ça n&#8217;existe pas déjà tout ça&nbsp;?</h2>
|
||
<p>Bien sur, il y a Google forms, qui vous permet de faire ce genre de
|
||
choses, mais comme je l&#8217;ai précisé plus haut, il ne s&#8217;agit pas
|
||
exactement de la même&nbsp;chose.</p>
|
||
<p>Nous avons découvert <a href="https://webform.com">https://webform.com</a> qui permet de créer des
|
||
formulaires avec un système de drag&#8217;n&#8217;drop. J&#8217;adorerais reproduire
|
||
quelque chose de similaire pour l&#8217;interface utilisateur. Par contre ce
|
||
projet ne gère pas les appels via <span class="caps">API</span> et les informations de
|
||
géolocalisation&nbsp;…</p>
|
||
<p>L&#8217;idée de <a href="http://thoth.io">http://thoth.io</a> est également assez sympathique: une api
|
||
très simple pour stocker et récupérer des données. En plus de ça,
|
||
<em>carto-forms</em> proposerait de la validation de données et proposerait un
|
||
support des points <span class="caps">SIG</span> (point, ligne,&nbsp;polygone).</p>
|
||
<p><a href="http://mapbox.com">http://mapbox.com</a> fait également un superbe travail autour de la
|
||
cartographie, mais ne prends pas en compte le coté auto-génération de&nbsp;formulaires…</p>
|
||
<h2 id="on-est-parti">On est parti&nbsp;?!</h2>
|
||
<p>Comme vous avez pu vous en rendre compte, il ne s&#8217;agit pas d&#8217;un problème
|
||
outrageusement complexe. On a pas mal discuté avec Mathieu, à propos de
|
||
ce qu&#8217;on souhaite faire et du comment. Il se trouve qu&#8217;on peut sûrement
|
||
s&#8217;en sortir avec une solution élégante sans trop de problèmes. Mathieu
|
||
est habitué à travailler autour des projets de <span class="caps">SIG</span> (ce qui est parfait
|
||
parce que ce n&#8217;est pas mon cas) et connaît son sujet. Une bonne
|
||
opportunité&nbsp;d&#8217;apprendre!</p>
|
||
<p>On sera tous les deux à <a href="http://rencontres.django-fr.org">Djangocong</a> le
|
||
14 et 15 Avril, et on prévoit une session de <em>tempête de cerveau</em> et un
|
||
sprint sur ce projet. Si vous êtes dans le coin et que vous souhaitez
|
||
discuter ou nous filer un coup de patte, n&#8217;hésitez&nbsp;pas!</p>
|
||
<p>On ne sait pas encore si on utilisera django ou quelque chose d&#8217;autre.
|
||
On a pensé un peu à CouchDB, son système de couchapps et geocouch, mais
|
||
rien n&#8217;est encore gravé dans le marbre ! N&#8217;hésitez pas à proposer vos
|
||
solutions ou&nbsp;suggestions.</p>
|
||
<p>Voici le document etherpad sur lequel on a travaillé jusqu&#8217;à maintenant:
|
||
<a href="http://framapad.org/carto-forms">http://framapad.org/carto-forms</a>. N&#8217;hésitez pas à l&#8217;éditer et à ajouter
|
||
vos commentaires, c&#8217;est son&nbsp;objectif!</p>
|
||
<p>Merci à <a href="http://sneakernet.fr/">Arnaud</a> pour la relecture et la
|
||
correction de quelques typos dans le texte&nbsp;:)</p></content><category term="code"></category></entry><entry><title>Thoughts about a form generation service, GIS enabled</title><link href="https://blog.notmyidea.org/thoughts-about-a-form-generation-service-gis-enabled.html" rel="alternate"></link><published>2012-04-02T00:00:00+02:00</published><updated>2012-04-02T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-04-02:/thoughts-about-a-form-generation-service-gis-enabled.html</id><summary type="html">
|
||
<p><em>Written by Alexis Métaireau <span class="amp">&amp;</span> Mathieu&nbsp;Leplatre</em></p>
|
||
<p>We have a plan. A &#8220;fucking good&#8221;&nbsp;one.</p>
|
||
<p>A bunch of friends asked me twice for quite the same thing: a webpage
|
||
with a form, tied to a map generation with some information filtering.
|
||
They didn&#8217;t explicitly ask that but that&#8217;s the …</p></summary><content type="html">
|
||
<p><em>Written by Alexis Métaireau <span class="amp">&amp;</span> Mathieu&nbsp;Leplatre</em></p>
|
||
<p>We have a plan. A &#8220;fucking good&#8221;&nbsp;one.</p>
|
||
<p>A bunch of friends asked me twice for quite the same thing: a webpage
|
||
with a form, tied to a map generation with some information filtering.
|
||
They didn&#8217;t explicitly ask that but that&#8217;s the gist of&nbsp;it.</p>
|
||
<p>This idea has been stuck in my head since then and I even think that we
|
||
can come out with something a little bit more flexible and useful. I&#8217;ve
|
||
named it <em>carto-forms</em> for now, but that&#8217;s only the&nbsp;&#8220;codename&#8221;.</p>
|
||
<p>To put it shortly: what if we had a way to build forms, ala Google
|
||
forms, but with geographic information in&nbsp;them?</p>
|
||
<p>If you don&#8217;t know Google forms, it means having an user-friendly way to
|
||
build forms and to use them to gather information from different&nbsp;users.</p>
|
||
<p>In my opinion, Google forms is missing two important things: first, it&#8217;s
|
||
not open-source, so it&#8217;s not possible to hack it or even to run it on
|
||
your own server. Second, it doesn&#8217;t really know how to deal with
|
||
geographic data, and there is no way to filter the information more than
|
||
in a&nbsp;spreadsheet.</p>
|
||
<p>I knew that <a href="http://blog.mathieu-leplatre.info/">Mathieu</a> and some folks
|
||
at <a href="http://makina-corpus.com">Makina Corpus</a> would be interested in
|
||
this, so I started a discussion with him on <span class="caps">IRC</span> and we refined the
|
||
details of the project and its&nbsp;objectives.</p>
|
||
<p>Imagine the&nbsp;following:</p>
|
||
<ol>
|
||
<li>For a mapping party, we choose a specific topic to map and design
|
||
the form (list of fields (i.e. tags) to be filled + description +
|
||
type of the information)&nbsp;;</li>
|
||
<li>In situ, users fill the form fields with what they see. Geo fields
|
||
can be pre-populated using device geolocation&nbsp;;</li>
|
||
<li>At the end of the day, we can see a map with all user contributions
|
||
seized through this particular form&nbsp;;</li>
|
||
<li>If relevant, a script could eventually import the resulting dataset
|
||
and publish/merge with&nbsp;OpenStreetMap.</li>
|
||
</ol>
|
||
<h2 id="some-use-cases">Some use&nbsp;cases</h2>
|
||
<p>I can see some use cases for this. The first one is a collaborative map,
|
||
with facet filtering. Let&#8217;s draw a potential user&nbsp;flow:</p>
|
||
<ul>
|
||
<li>
|
||
<p>An &#8220;administrator&#8221; goes to the website and creates a form to list
|
||
all the alternative-related events. He creates the following&nbsp;fields:</p>
|
||
<ul>
|
||
<li>Name: a plain text field containing the name of the&nbsp;event.</li>
|
||
<li>Category: the category of the event. Can be a finite&nbsp;list.</li>
|
||
<li>Location: The location of the event. It could be provided by
|
||
selecting a point on a map or by typing an&nbsp;address.</li>
|
||
<li>Date: the date of the event (a datepicker could do the&nbsp;trick)</li>
|
||
</ul>
|
||
<p>Each field in the form has semantic information associated with it
|
||
(yes/no, multiple selection, date-time, geocoding carto, carto
|
||
selection&nbsp;etc)</p>
|
||
</li>
|
||
<li>
|
||
<p>Once finished, the form is generated and the user gets an url (say
|
||
<a href="http://forms.notmyidea.org/alternatives">http://forms.notmyidea.org/alternatives</a>) for&nbsp;it.</p>
|
||
</li>
|
||
<li>
|
||
<p><span class="caps">REST</span> APIs allow third parties to get the form description and to
|
||
push/edit/get information from&nbsp;there.</p>
|
||
</li>
|
||
<li>
|
||
<p>He can communicate the address in any way he wants to his community
|
||
so they can go to the page and add information to&nbsp;it.</p>
|
||
</li>
|
||
<li>
|
||
<p>Then, it is possible to filter the results per location / date or
|
||
category. This can be done via <span class="caps">API</span> calls (useful for third parties)
|
||
or via a nice interface in the&nbsp;browser.</p>
|
||
</li>
|
||
</ul>
|
||
<p>So, as you may have noticed, this would allow us to create interactive
|
||
maps really easily. It&#8217;s almost just a matter of some clicks to the
|
||
users. If we also come up with a nice Web <span class="caps">API</span> for this, we could do
|
||
server-side validation and build even phone applications&nbsp;easily.</p>
|
||
<p>To push the cursor a bit further, if we can come with a cool description
|
||
format for the forms, we could even build the forms dynamically on
|
||
different platforms, with generic&nbsp;clients.</p>
|
||
<p>As mentioned before, the idea of a simple tool to support collaborative
|
||
mapping fullfils a recurring necessity&nbsp;!</p>
|
||
<p>We envision a lot of example uses for this : recycling spots, accessible
|
||
spots (wheelchairs, etc.), trees identification, mushrooms picking
|
||
areas, tracking of endangered species (e.g. Bonelli&#8217;s Eagle is currently
|
||
tracked by sharing a spreadsheet), spotting of dangerous species (e.g.
|
||
asian predatory wasps), map advertisement boards (most cities do not
|
||
track them!), citizen reporting (e.g. graffiti, potholes, garbage,
|
||
lightning like <a href="http://fixmystreet.ca">http://fixmystreet.ca</a>), geocaching, trajectories (e.g
|
||
hiking, runners,&nbsp;cyclists)&#8230;</p>
|
||
<p>Here are some other examples of where <em>carto-forms</em> could be&nbsp;useful:</p>
|
||
<h3 id="simple-gis-storage-backend">Simple <span class="caps">GIS</span> storage&nbsp;backend</h3>
|
||
<p>Let&#8217;s say you are a mobile developer, you don&#8217;t want to bother with
|
||
PostGIS nor write a custom and insecure code to insert and retrieve your
|
||
<span class="caps">GIS</span> data! You need carto-forms! A simple <span class="caps">API</span> helps you design your
|
||
models/forms and the same <span class="caps">API</span> allows you to <span class="caps">CRUD</span> and query your data.
|
||
Thus, you only need to focus on your application, not on how <span class="caps">GIS</span> data
|
||
will be&nbsp;handled.</p>
|
||
<p>We make a distinction between storage and&nbsp;widgets.</p>
|
||
<p>Besides, if you are a django / drupal / plomino&#8230; maintainer : you can
|
||
develop a module to &#8220;plug&#8221; your models (content types) and <span class="caps">UI</span> to
|
||
carto-forms! Carto forms are then exposed to your backoffice users (ex:
|
||
drupal admin <span class="caps">UI</span>, django adminsite), and likewise you can write your own
|
||
<span class="caps">HTML</span> widgets that consume datasets in frontend views (facets in
|
||
<span class="caps">JSON</span>/<span class="caps">XML</span>, and map data in&nbsp;GeoJSON).</p>
|
||
<h3 id="visualization-tool">Visualization&nbsp;tool</h3>
|
||
<p>Since data submission can be done programmatically using the <span class="caps">API</span>, you
|
||
could use Carto-forms results page as a visualization&nbsp;tool.</p>
|
||
<p>You can explore your dataset content using filters related to each form
|
||
field. Facets filtering is a great advantage, and a map shows the
|
||
resulting features set. You feel like you&#8217;re in front of a decision
|
||
support&nbsp;system!</p>
|
||
<p>Of course, filtered raw data can be downloaded (GeoJSON, <span class="caps">XML</span>) and a
|
||
permalink allows to share the page with the state of the filters and the
|
||
zoom/location of the&nbsp;map.</p>
|
||
<h3 id="generic-forms-service">Generic forms&nbsp;service</h3>
|
||
<p>If you want to generate a configuration file (or whatever, email
|
||
messages, &#8230;), you will need a form and a template to inlay user
|
||
submitted values and get the&nbsp;result.</p>
|
||
<p>A form service would be really useful to create forms programmatically
|
||
and retrieve cleaned and validated input&nbsp;values.</p>
|
||
<p>You could run a dedicated template service based on <em>carto-forms</em>!
|
||
Parsing a template content, this external service could create a form
|
||
dynamically and bind them together. The output of the form service
|
||
(fields =&gt; values) would be bound to the input of a template engine
|
||
(variables =&gt; final&nbsp;result).</p>
|
||
<p>Note that for this use-case, there is no specific need of <span class="caps">GIS</span> data nor
|
||
storage of records for further&nbsp;retrieval.</p>
|
||
<h2 id="whats-out-in-the-wild-already">What&#8217;s out in the wild&nbsp;already?</h2>
|
||
<p>Of course, there is Google forms, which allows you to do these kind of
|
||
things, but it&#8217;s closed and not exactly what we are describing&nbsp;here.</p>
|
||
<p>We&#8217;ve discovered the interesting <a href="https://webform.com/">https://webform.com/</a> which allows one
|
||
to create forms with a nice drag-n-drop flow. I would love to reproduce
|
||
something similar for the user experience. However, the project doesn&#8217;t
|
||
handle APIs and geolocation&nbsp;information.</p>
|
||
<p>The idea of <a href="http://thoth.io">http://thoth.io</a> is very attractive : an extremely simple
|
||
web <span class="caps">API</span> to store and retrieve data. In addition, <em>carto-forms</em> would do
|
||
datatype validation and have basic <span class="caps">GIS</span> fields (point, line,&nbsp;polygon).</p>
|
||
<p><a href="http://mapbox.com">http://mapbox.com</a> also did an awesome work on cartography, but didn&#8217;t
|
||
take into account the form aspect we&#8217;re leveraging&nbsp;here.</p>
|
||
<h2 id="so-lets-get-it-real">So… Let&#8217;s get it&nbsp;real!</h2>
|
||
<p>As you may have understood, this isn&#8217;t a really complicated problem. We
|
||
have been sometimes chatting about that with Mathieu about what we would
|
||
need and how we could achieve&nbsp;this.</p>
|
||
<p>We can probably come with an elegant solution without too much pain.
|
||
Mathieu is used to work with <span class="caps">GIS</span> systems (which is really cool because
|
||
I&#8217;m not at all) and knows his subject, so that&#8217;s an opportunity to learn&nbsp;;-)</p>
|
||
<p>We will be at <a href="http://rencontres.django-fr.org">Djangocong</a> on April 14
|
||
and 15 and will probably have a brainstorming session and a sprint on
|
||
this, so if you are around and want to help us, or just to discuss, feel
|
||
free to&nbsp;join!</p>
|
||
<p>We don&#8217;t know yet if we will be using django for this or something else.
|
||
We have been thinking about couchdb, couchapps and geocouch but nothing
|
||
is written in stone yet. Comments and proposals are&nbsp;welcome!</p>
|
||
<p>Here is the etherpad document we worked on so far:
|
||
<a href="http://framapad.org/carto-forms">http://framapad.org/carto-forms</a>. Don&#8217;t hesitate to add your thoughts
|
||
and edit it, that&#8217;s what it&#8217;s made&nbsp;for!</p>
|
||
<p>Thanks to <a href="http://sneakernet.fr/">Arnaud</a> and
|
||
<a href="http://qwerty.fuzz.me.uk/">Fuzzmz</a> for proof-reading and typo&nbsp;fixing.</p></content><category term="code"></category></entry><entry><title>Les dangers du livre numérique</title><link href="https://blog.notmyidea.org/les-dangers-du-livre-numerique.html" rel="alternate"></link><published>2012-01-23T00:00:00+01:00</published><updated>2012-01-23T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-01-23:/les-dangers-du-livre-numerique.html</id><summary type="html">
|
||
<p>Le framablog vient de publier <a href="http://www.framablog.org/index.php/post/2012/01/22/stallman-ebook-livre-electronique">une traduction de l&#8217;article de <span class="caps">RMS</span> à
|
||
propos des dangers du livre
|
||
électronique</a>.
|
||
Intéressant, même si il faut faire attention à ne pas confondre livre
|
||
électronique et risques liés au format de&nbsp;distribution.</p>
|
||
<p>Si on passe sur le fait qu&#8217;un livre électronique est …</p></summary><content type="html">
|
||
<p>Le framablog vient de publier <a href="http://www.framablog.org/index.php/post/2012/01/22/stallman-ebook-livre-electronique">une traduction de l&#8217;article de <span class="caps">RMS</span> à
|
||
propos des dangers du livre
|
||
électronique</a>.
|
||
Intéressant, même si il faut faire attention à ne pas confondre livre
|
||
électronique et risques liés au format de&nbsp;distribution.</p>
|
||
<p>Si on passe sur le fait qu&#8217;un livre électronique est moins agréable à lire que sa version papier, il reste quand même quelques problèmes, la plupart liés au format de distribution de&nbsp;l’œuvre.</p>
|
||
<p>J&#8217;avoue ne pas trop savoir quoi penser de tout ça. D&#8217;un coté le livre électronique permet de franchir les frontières plus facilement, et semble avoir un tas d&#8217;avantage (notamment le fait que se trimbaler avec l&#8217;ensemble de sa collection de bouquins est désormais&nbsp;possible).</p>
|
||
<p>A mon avis, ce qui pose vraiment problème, ce sont les formats sous
|
||
lesquels ces livres sont mis à disposition, non pas les livres eux même.
|
||
Encore une question de DRMs&nbsp;donc…</p>
|
||
<p>Encore une problématique liée au copyright et au fait que le copie
|
||
privée pose des problèmes à l&#8217;industrie en place. Ça renvoie à des
|
||
questions plus profondes, et principalement à la mise en perspective du
|
||
producteur de contenu et du consomateur de ce même contenu. Exactement
|
||
ce qu&#8217;on essaye de résoudre dans le milieu agricole par le biais des&nbsp;AMAPs.</p>
|
||
<p>Sauf qu&#8217;ici, on est face au simple problème de la dématérialisation.
|
||
Est-ce qu&#8217;une responsabilisation des consommateurs ne pourrait pas
|
||
résoudre ce problème de publication&nbsp;?</p>
|
||
<p>Recemment, j&#8217;ai récupéré une version piratée d&#8217;un livre technique,
|
||
simplement parce que je ne trouvais pas une version de ce livre en
|
||
numérique qui me permette de faire une copie privée de celui ci. Un
|
||
Epub, par exemple. J&#8217;ai fait en me disant que c&#8217;était un acte militant.
|
||
Sauf que non, ce n&#8217;est pas une solution soutenable, et j&#8217;en viens
|
||
maintenant presque à le regretter. On en discutait rapidement avec
|
||
<a href="http://ziade.org">Tarek</a> il y à quelques jours et il pointait du doigt
|
||
que ceux qui en patissent sont les auteurs des livres, non pas les
|
||
éditeurs (qu&#8217;il ne faut pas non plus diaboliser selon moi, ils
|
||
cherchent à trouver des manières de garder leur coeur de&nbsp;métier).</p>
|
||
<p>Or, avoir des auteurs, des personnes qui sont prêtes à partager leur
|
||
savoir à de larges audiences me semble primordial pour que la
|
||
répartition du savoir continue à se répendre. Certes, le blogging
|
||
permet cela dans une faible mesure, mais de manière bien moins
|
||
construite, et surtout, est fait de manière bénévole (à moins que
|
||
certains bloggeurs aient trouvé des moyens de rémunération dont j&#8217;ignore
|
||
l&#8217;existance ?), donc il est plus difficile pour les auteurs de se
|
||
dégager du temps pour travailler sur de gros ouvrages (ceci est bien
|
||
évidemment une&nbsp;généralisation).</p>
|
||
<p>Quelles sont nos solutions, donc ? Peut être se tourner vers des
|
||
solution de publication alternatives, couplées à une résponsabilisation
|
||
des lecteurs. Je ne pense pas necessairement aux plateformes
|
||
alternatives comme <a href="http://framabook.org">framabook</a>, parce que je me
|
||
demande toujours si cela est une solution viable pour les auteurs, du
|
||
moins dans les premières années, mais au moins des éditeurs qui ne font
|
||
pas le choix du grand verrou&nbsp;numérique.</p>
|
||
<p>On demande pas grand chose, pourtant… Peut être même que de telles
|
||
initiatives existent déjà&nbsp;?</p>
|
||
<p>Et vous, vous les achetez ou vos livres&nbsp;?</p></content><category term="journal"></category></entry><entry><title>Mozilla, first months</title><link href="https://blog.notmyidea.org/mozilla-first-months.html" rel="alternate"></link><published>2012-01-21T00:00:00+01:00</published><updated>2012-01-21T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2012-01-21:/mozilla-first-months.html</id><summary type="html">
|
||
<p>A lot of changes in these last months. First of all, I&#8217;ve started to work for <a href="http://mozilla.org">Mozilla</a>, on the Services team, where I am
|
||
working on web services and scalability. Basically, what we are trying
|
||
to do at services is to provide a way for developers to make web …</p></summary><content type="html">
|
||
<p>A lot of changes in these last months. First of all, I&#8217;ve started to work for <a href="http://mozilla.org">Mozilla</a>, on the Services team, where I am
|
||
working on web services and scalability. Basically, what we are trying
|
||
to do at services is to provide a way for developers to make web
|
||
services able to scale out of the&nbsp;box.</p>
|
||
<p>Our most visible and known project, so far, is Firefox Sync, which
|
||
allows to synchronize browsing data (tabs, passwords, history, etc.)
|
||
among different instances of Firefox. We are also building other things,
|
||
such as a way to get metrics easily, a web service based queue, etc. Our
|
||
primary consumers are people inside Mozilla, and we want to help them
|
||
having a simple way to create, deploy and scale their apps. The project
|
||
is named &#8220;sagrada&#8221;, and you can find some more information about it on
|
||
<a href="https://wiki.mozilla.org/Services/Sagrada">our public&nbsp;wiki</a></p>
|
||
<p>All of what we do, we do it in the open. So you can have a look at <a href="http://github.com/mozilla-services">the
|
||
different pieces of code we wrote</a>
|
||
and use them / contribute if you want&nbsp;to.</p>
|
||
<p>I will not dig in to all the details of what I have been doing, but so
|
||
far, this have been a pretty amazing experience. Part of this is
|
||
explainable by the fact that the team is made of amazing folks, all with
|
||
a strong experience in different topics, so I&#8217;m learning&nbsp;things™.</p>
|
||
<p>I am currently practicing a bit my C++ to do crypto related things (I
|
||
may or may not talk about this later on this web-logs) and it&#8217;s great
|
||
(well, it remembers me why I love python for so many things, but it
|
||
makes me think closer to the metal ;)). I love this&nbsp;job.</p>
|
||
<p>Second, I moved to Paris. Yes, Paris. Some of you who know me a bit may
|
||
find it unexpected, and that&#8217;s the case. I&#8217;m usually not a big fan of
|
||
big cities and am a fairly strong defender of having and creating
|
||
activities in the country side, to face the rural exodus problem, into
|
||
other&nbsp;thingS.</p>
|
||
<p>I didn&#8217;t changed my opinion about that. However, I don&#8217;t want to <em>start</em>
|
||
by working remote, especially when working with a remote team. Having
|
||
offices kind of help me to have a differentiation between my working
|
||
place and home, which I find to be&nbsp;important.</p>
|
||
<p>And, to be honest, I don&#8217;t like Paris for unknown reasons: I haven&#8217;t
|
||
been there, so it&#8217;s a big over-generalisation to say that it&#8217;s not good
|
||
for me. The reality is that I have no idea of what Paris is, and if I&#8217;ll
|
||
like it or&nbsp;not.</p>
|
||
<p>I found a really nice house (yeah, a house!) in Paris and am sharing it
|
||
with 3 other persons. We have room, all like good food and… they are not
|
||
geeks, which is a big win for me: work is work and home is&nbsp;home.</p>
|
||
<p>So far, Paris had been really nice. A lot of things are going on in
|
||
here, and I kind of like the way it is possible to find alternative
|
||
related things in here. I found a
|
||
<a href="http://en.wikipedia.org/wiki/Community-supported_agriculture"><span class="caps">CSA</span></a>,
|
||
some people interested by agriculture related problems and I like where
|
||
things seems to be&nbsp;going.</p>
|
||
<p>So, new job, new house, new city, things are going forward and that&#8217;s&nbsp;great.</p>
|
||
<p>Oh, and I will try to post some more technical articles soon, I&#8217;m
|
||
missing them&nbsp;:)</p></content><category term="journal"></category></entry><entry><title>Introducing Cornice</title><link href="https://blog.notmyidea.org/introducing-cornice.html" rel="alternate"></link><published>2011-12-07T00:00:00+01:00</published><updated>2011-12-07T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-12-07:/introducing-cornice.html</id><summary type="html">
|
||
<p>Wow, already my third working day at Mozilla. Since Monday, I&#8217;ve been
|
||
working with <a href="http://ziade.org">Tarek Ziadé</a>, on a pyramid <span class="caps">REST</span>-ish
|
||
toolkit named <a href="https://github.com/mozilla-services/cornice">Cornice</a>.</p>
|
||
<p>Its goal is to take care for you of what you&#8217;re usually missing so you
|
||
can focus on what&#8217;s important. Cornice provides you …</p></summary><content type="html">
|
||
<p>Wow, already my third working day at Mozilla. Since Monday, I&#8217;ve been
|
||
working with <a href="http://ziade.org">Tarek Ziadé</a>, on a pyramid <span class="caps">REST</span>-ish
|
||
toolkit named <a href="https://github.com/mozilla-services/cornice">Cornice</a>.</p>
|
||
<p>Its goal is to take care for you of what you&#8217;re usually missing so you
|
||
can focus on what&#8217;s important. Cornice provides you facilities for
|
||
validation of any&nbsp;kind.</p>
|
||
<p>The goal is to simplify your work, but we don&#8217;t want to reinvent the
|
||
wheel, so it is easily pluggable with validations frameworks, such as
|
||
<a href="http://docs.pylonsproject.org/projects/colander/en/latest/">Colander</a>.</p>
|
||
<h2 id="handling-errors-and-validation">Handling errors and&nbsp;validation</h2>
|
||
<p>Here is how it&nbsp;works:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">service</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;service&quot;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s2">&quot;/service&quot;</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">is_awesome</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="s1">&#39;awesome&#39;</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="p">:</span>
|
||
<span class="n">request</span><span class="o">.</span><span class="n">errors</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">&#39;query&#39;</span><span class="p">,</span> <span class="s1">&#39;awesome&#39;</span><span class="p">,</span>
|
||
<span class="s1">&#39;the awesome parameter is required&#39;</span><span class="p">)</span>
|
||
|
||
|
||
<span class="nd">@service</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">validator</span><span class="o">=</span><span class="n">is_awesome</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">get1</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="p">{</span><span class="s2">&quot;test&quot;</span><span class="p">:</span> <span class="s2">&quot;yay!&quot;</span><span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>All the errors collected during the validation process, or after, are
|
||
collected before returning the request. If any, a error 400 is fired up,
|
||
with the list of problems encountered returned as a nice json list
|
||
response (we plan to support multiple formats in the&nbsp;future)</p>
|
||
<p>As you might have seen, request.errors.add takes three parameters:
|
||
<strong>location</strong>, <strong>name</strong> and <strong>description</strong>.</p>
|
||
<p><strong>location</strong> is where the error is located in the request. It can either
|
||
be &#8220;body&#8221;, &#8220;query&#8221;, &#8220;headers&#8221; or &#8220;path&#8221;. <strong>name</strong> is the name of the
|
||
variable causing problem, if any, and <strong>description</strong> contains a more
|
||
detailed&nbsp;message.</p>
|
||
<p>Let&#8217;s run this simple service and send some queries to&nbsp;it:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>curl<span class="w"> </span>-v<span class="w"> </span>http://127.0.0.1:5000/service
|
||
&gt;<span class="w"> </span>GET<span class="w"> </span>/service<span class="w"> </span>HTTP/1.1
|
||
&gt;<span class="w"> </span>Host:<span class="w"> </span><span class="m">127</span>.0.0.1:5000
|
||
&gt;<span class="w"> </span>Accept:<span class="w"> </span>*/*
|
||
&gt;
|
||
*<span class="w"> </span>HTTP<span class="w"> </span><span class="m">1</span>.0,<span class="w"> </span>assume<span class="w"> </span>close<span class="w"> </span>after<span class="w"> </span>body
|
||
&lt;<span class="w"> </span>HTTP/1.0<span class="w"> </span><span class="m">400</span><span class="w"> </span>Bad<span class="w"> </span>Request
|
||
&lt;<span class="w"> </span>Content-Type:<span class="w"> </span>application/json<span class="p">;</span><span class="w"> </span><span class="nv">charset</span><span class="o">=</span>UTF-8
|
||
<span class="o">[{</span><span class="s2">&quot;location&quot;</span>:<span class="w"> </span><span class="s2">&quot;query&quot;</span>,<span class="w"> </span><span class="s2">&quot;name&quot;</span>:<span class="w"> </span><span class="s2">&quot;awesome&quot;</span>,<span class="w"> </span><span class="s2">&quot;description&quot;</span>:<span class="w"> </span><span class="s2">&quot;You lack awesomeness!&quot;</span><span class="o">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>I&#8217;ve removed the extra clutter from the curl&#8217;s output, but you got the
|
||
general&nbsp;idea.</p>
|
||
<p>The content returned is in <span class="caps">JSON</span>, and I know exactly what I have to do:
|
||
add an &#8220;awesome&#8221; parameter in my query. Let&#8217;s do it&nbsp;again:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>curl<span class="w"> </span>http://127.0.0.1:5000/service?awesome<span class="o">=</span>yeah
|
||
<span class="o">{</span><span class="s2">&quot;test&quot;</span>:<span class="w"> </span><span class="s2">&quot;yay!&quot;</span><span class="o">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>Validators can also convert parts of the request and store the converted
|
||
value in request.validated. It is a standard dict automatically attached
|
||
to the&nbsp;requests.</p>
|
||
<p>For instance, in our validator, we can chose to validate the parameter
|
||
passed and use it in the body of the&nbsp;webservice:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">service</span> <span class="o">=</span> <span class="n">Service</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;service&quot;</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="s2">&quot;/service&quot;</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">is_awesome</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="s1">&#39;awesome&#39;</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="p">:</span>
|
||
<span class="n">request</span><span class="o">.</span><span class="n">errors</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s1">&#39;query&#39;</span><span class="p">,</span> <span class="s1">&#39;awesome&#39;</span><span class="p">,</span>
|
||
<span class="s1">&#39;the awesome parameter is required&#39;</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">request</span><span class="o">.</span><span class="n">validated</span><span class="p">[</span><span class="s1">&#39;awesome&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;awesome &#39;</span> <span class="o">+</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="p">[</span><span class="s1">&#39;awesome&#39;</span><span class="p">]</span>
|
||
|
||
|
||
<span class="nd">@service</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">validator</span><span class="o">=</span><span class="n">is_awesome</span><span class="p">)</span>
|
||
<span class="k">def</span> <span class="nf">get1</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="p">{</span><span class="s2">&quot;test&quot;</span><span class="p">:</span> <span class="n">request</span><span class="o">.</span><span class="n">validated</span><span class="p">[</span><span class="s1">&#39;awesome&#39;</span><span class="p">]}</span>
|
||
</code></pre></div>
|
||
|
||
<p>The output would look like&nbsp;this:</p>
|
||
<div class="highlight"><pre><span></span><code>curl http://127.0.0.1:5000/service?awesome=yeah
|
||
{&quot;test&quot;: &quot;awesome yeah&quot;}
|
||
</code></pre></div>
|
||
|
||
<h2 id="dealing-with-accept-headers">Dealing with &#8220;Accept&#8221;&nbsp;headers</h2>
|
||
<p>The <span class="caps">HTTP</span> spec defines a <strong>Accept</strong> header the client can send so the
|
||
response is encoded the right way. A resource, available at an <span class="caps">URL</span>, can
|
||
be available in different formats. This is especially true for web&nbsp;services.</p>
|
||
<p>Cornice can help you dealing with this. The services you define can tell
|
||
which Content-Type values they can deal with and this will be checked
|
||
against the <strong>Accept</strong> headers sent by the&nbsp;client.</p>
|
||
<p>Let&#8217;s refine a bit our previous example, by specifying which
|
||
content-types are supported, using the accept&nbsp;parameter:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nd">@service</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">validator</span><span class="o">=</span><span class="n">is_awesome</span><span class="p">,</span> <span class="n">accept</span><span class="o">=</span><span class="p">(</span><span class="s2">&quot;application/json&quot;</span><span class="p">,</span> <span class="s2">&quot;text/json&quot;</span><span class="p">))</span>
|
||
<span class="k">def</span> <span class="nf">get1</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="p">{</span><span class="s2">&quot;test&quot;</span><span class="p">:</span> <span class="s2">&quot;yay!&quot;</span><span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>Now, if you specifically ask for <span class="caps">XML</span>, Cornice will throw a 406 with the
|
||
list of accepted Content-Type&nbsp;values:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>curl<span class="w"> </span>-vH<span class="w"> </span><span class="s2">&quot;Accept: application/xml&quot;</span><span class="w"> </span>http://127.0.0.1:5000/service
|
||
&gt;<span class="w"> </span>GET<span class="w"> </span>/service<span class="w"> </span>HTTP/1.1
|
||
&gt;<span class="w"> </span>Host:<span class="w"> </span><span class="m">127</span>.0.0.1:5000
|
||
&gt;<span class="w"> </span>Accept:<span class="w"> </span>application/xml
|
||
&gt;
|
||
&lt;<span class="w"> </span>HTTP/1.0<span class="w"> </span><span class="m">406</span><span class="w"> </span>Not<span class="w"> </span>Acceptable
|
||
&lt;<span class="w"> </span>Content-Type:<span class="w"> </span>application/json<span class="p">;</span><span class="w"> </span><span class="nv">charset</span><span class="o">=</span>UTF-8
|
||
&lt;<span class="w"> </span>Content-Length:<span class="w"> </span><span class="m">33</span>
|
||
&lt;
|
||
<span class="o">[</span><span class="s2">&quot;application/json&quot;</span>,<span class="w"> </span><span class="s2">&quot;text/json&quot;</span><span class="o">]</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="building-your-documentation-automatically">Building your documentation&nbsp;automatically</h2>
|
||
<p>writing documentation for web services can be painful, especially when
|
||
your services evolve. Cornice provides a sphinx directive to
|
||
automatically document your <span class="caps">API</span> in your&nbsp;docs.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nx">rst</span>
|
||
<span class="p">..</span><span class="w"> </span><span class="nx">services</span><span class="o">::</span>
|
||
<span class="w"> </span><span class="p">:</span><span class="kn">package</span><span class="p">:</span><span class="w"> </span><span class="nx">coolapp</span>
|
||
<span class="w"> </span><span class="p">:</span><span class="nx">service</span><span class="p">:</span><span class="w"> </span><span class="nx">quote</span>
|
||
</code></pre></div>
|
||
|
||
<p>Here is an example of what a generated page looks like:
|
||
<a href="http://packages.python.org/cornice/exampledoc.html">http://packages.python.org/cornice/exampledoc.html</a></p>
|
||
<h2 id="yay-how-can-i-get-it">Yay! How can I get&nbsp;it?</h2>
|
||
<p>We just cut a 0.4 release, so it&#8217;s available at
|
||
<a href="http://pypi.python.org/pypi/cornice">http://pypi.python.org/pypi/cornice</a> You can install it easily using
|
||
pip, for&nbsp;instance:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>cornice
|
||
</code></pre></div>
|
||
|
||
<p>You can also have a look at the documentation at
|
||
<a href="http://packages.python.org/cornice/">http://packages.python.org/cornice/</a></p>
|
||
<h2 id="whats-next">What&#8217;s&nbsp;next?</h2>
|
||
<p>We try to make our best to find how Cornice can help you build better
|
||
web services. Cool features we want for the future include the automatic
|
||
publication of a static definition of the services, so it can be used by
|
||
clients to discover services in a nice&nbsp;way.</p>
|
||
<p>Of course, we are open to all your ideas and patches! If you feel
|
||
haskish and want to see the sources, <a href="https://github.com/mozilla-services/cornice">go grab them on
|
||
github</a> , commit and send
|
||
us a pull&nbsp;request!</p></content><category term="code"></category></entry><entry><title>Quels usages pour l’informatique ?</title><link href="https://blog.notmyidea.org/quels-usages-pour-linformatique.html" rel="alternate"></link><published>2011-12-01T00:00:00+01:00</published><updated>2011-12-01T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-12-01:/quels-usages-pour-linformatique.html</id><summary type="html">
|
||
<p>Quand on termine ses études, on s&#8217;en pose un tas, des questions. Sur le
|
||
métier que l&#8217;on veut faire, sur ce que ça signifie, sur le sens et la
|
||
valeur du travail. Et j&#8217;en suis arrivé à faire un constat simple:
|
||
l&#8217;informatique, c&#8217;est utile, tant …</p></summary><content type="html">
|
||
<p>Quand on termine ses études, on s&#8217;en pose un tas, des questions. Sur le
|
||
métier que l&#8217;on veut faire, sur ce que ça signifie, sur le sens et la
|
||
valeur du travail. Et j&#8217;en suis arrivé à faire un constat simple:
|
||
l&#8217;informatique, c&#8217;est utile, tant que ça ne vient pas vous pourrir la
|
||
vie. Oui, parce que de l&#8217;informatique on en a partout, des &#8220;geeks&#8221; et
|
||
des &#8220;accros&#8221; aussi, et que ça vient s&#8217;immiscer dans nos vies même quand
|
||
d&#8217;autres moyens ou médias sont plus utiles ou&nbsp;pertinents.</p>
|
||
<p>Certes, l&#8217;informatique nous permet de communiquer et travailler plus
|
||
efficacement, Mais à quel prix ? Ce n&#8217;est pas parce qu&#8217;il est possible
|
||
d&#8217;<a href="http://retourdactu.fr/2011/11/07/la-non-communication-nouveau-modele-de-societe/">industrialiser
|
||
l&#8217;éducation</a>
|
||
(ou l&#8217;agriculture !), que l&#8217;on doit le faire. Oui, ça me dérange d&#8217;être
|
||
une des nombreuses personnes à l&#8217;œuvre derrière cette soit disant
|
||
&#8220;révolution&#8221;, qui n&#8217;est pas toujours pour le meilleur. Attention, je ne
|
||
remets pas l&#8217;informatique et son intérêt en cause: je me pose des
|
||
questions quand à la place que je veux lui donner et la place que je
|
||
souhaites occuper dans son évolution. Ce n&#8217;est pas parce qu&#8217;on peut tuer
|
||
avec un marteau (avec un peu de volonté) qu&#8217;il s&#8217;agit d&#8217;un mauvais
|
||
outil, mais si tout le monde se met à tuer avec des marteaux (y a des
|
||
malades partout, hein), alors se poser la question de son rôle, en tant
|
||
que fabricant de marteaux me semble nécessaire (oui, je vous l&#8217;accorde,
|
||
on aura vu des comparaisons plus&nbsp;perspicaces).</p>
|
||
<p>Donc: à partir de quel moment l&#8217;informatique cesse d&#8217;être un outil utile
|
||
pour transformer nos modes de vies d&#8217;une manière qui me dérange ? Peut
|
||
être avec son arrivée sur des périphériques mobiles ? Peut être quand
|
||
elle se fait l&#8217;instrument du consumérisme et de&nbsp;l&#8217;individualisme.</p>
|
||
<h2 id="et-alors-on-fait-quoi">Et alors, on fait quoi&nbsp;?</h2>
|
||
<p>Mais si je continue à faire de l&#8217;informatique, il y a bien des raison.
|
||
J&#8217;ai d&#8217;ailleurs trouvé mon intérêt de par le coté collaboratif qui est
|
||
permis et développé par l&#8217;outil informatique, et notamment par le réseau
|
||
des réseaux (internet). Faisons ensemble, mes amis. Prouvons que la
|
||
collaboration a de meilleurs jours à vivre que la compétition. Le web,
|
||
notamment, est une avancée majeure en ce qui concerne la liberté
|
||
d&#8217;expression et le partage de connaissances (oui, kipédia). Je vous
|
||
conseille d&#8217;ailleurs à ce propos <a href="http://owni.fr/2011/11/30/vers-une-economie-de-la-contribution/">l&#8217;excellent discours tenu par Bernard
|
||
Stiegler</a>
|
||
paru récemment sur <a href="http://www.owni.fr">owni</a>.</p>
|
||
<p>Et c&#8217;est cet avenir qu&#8217;il me plait de défendre: l&#8217;ouverture d&#8217;esprit, la
|
||
possibilité que chacun puisse contribuer et participer à une base de
|
||
savoir commune, en apprenant des autres. Mais par pitié, n&#8217;imposons pas
|
||
la technologie là où elle n&#8217;est pas nécessaire, et utilisons la avec
|
||
tact quand elle peut nous être&nbsp;profitable.</p>
|
||
<p>Il me plait de repenser l&#8217;informatique comme outil et non plus comme
|
||
mode de vie. Faisons le l&#8217;outil de la collaboration. À l&#8217;école,
|
||
apprenons à nos enfants à collaborer, à susciter le partage, pas
|
||
uniquement avec l&#8217;outil informatique, mais aussi avec celui ci, tout en
|
||
leurs apprenant à avoir un regard critique sur les informations qu&#8217;ils&nbsp;reçoivent.</p>
|
||
<p>En bref, questionner le rôle que l&#8217;on souhaite avoir dans notre société
|
||
par le biais de l&#8217;informatique est nécessaire. Comme d&#8217;autres, je suis
|
||
arrivé à l&#8217;informatique par le biais du premier ordinateur familial, il
|
||
y a de ça une bonne quinzaine d&#8217;années. Ça intrigue, on touche un peu à
|
||
tout (on en fait des conneries !) et on finit par apprendre/comprendre
|
||
comment ça marche, petit à petit. Cette curiosité n&#8217;est d&#8217;ailleurs pas
|
||
le propre de l&#8217;informatique puisqu&#8217;on la retrouve dans la cuisine, dans
|
||
le bricolage et dans un tas de domaines de notre vie&nbsp;quotidienne.</p>
|
||
<p>Finalement, c&#8217;est aimer bidouiller, et comprendre comment ça fonctionne,
|
||
quitte à sortir les compétences de leur domaine de prédilection (qui a
|
||
dit que l&#8217;informatique ne pouvait être artistique ?) Le mouvement hacker
|
||
(bidouilleurs) aime à sortir l&#8217;informatique de son carcan et l&#8217;appliquer&nbsp;ailleurs.</p>
|
||
<p>C&#8217;est de cette manière que j&#8217;ai envie de considérer mon métier, qui
|
||
avant tout est une passion. Je suis un bidouilleur, j&#8217;aime découvrir
|
||
comment les choses fonctionnent et avoir une panoplie d&#8217;outils qui me
|
||
permettent de répondre à des besoins&nbsp;réels.</p>
|
||
<h2 id="favoriser-la-collaboration">Favoriser la&nbsp;collaboration</h2>
|
||
<p>Et donc, en tant qu&#8217;individu, pourquoi faire de l&#8217;informatique ?
|
||
Qu&#8217;est-ce qui m&#8217;attire dans cet outil&nbsp;?</p>
|
||
<p>Ce qu&#8217;on pourrait qualifier de &#8220;recherche fondamentale&#8221;, l&#8217;écriture de
|
||
bibliothèques logicielles, est important mais n&#8217;est pas tout. Ce qui
|
||
importe ce sont les usages qui en découlent. Je souhaite <strong>savoir écrire
|
||
des outils qui sont utiles</strong>, <strong>qui favorisent la collaboration et
|
||
participent à l&#8217;ouverture des esprits</strong>.</p>
|
||
<p>Je choisis de faire de l&#8217;informatique pour créer les outils qui
|
||
répondent à des problématiques réelles, pour trouver de meilleures
|
||
manières de communiquer et de travailler ensemble. Mais, comme me le
|
||
disait David,
|
||
d&#8217;<a href="http://outils-reseaux.org/PresentationProjet">Outils-Réseaux</a>, on ne
|
||
crée pas de la coopération: rien ne sert d&#8217;essayer de faire coopérer des
|
||
gens qui ne veulent pas. On peut, cependant, la faciliter, en utilisant
|
||
les bons outils et en formant les gens à leur utilisation, ainsi qu&#8217;aux
|
||
pratiques collaboratives (qui, je le répète, ne s&#8217;arrêtent pas du tout
|
||
aux frontières&nbsp;informatique).</p>
|
||
<p>Le logiciel libre, avant d&#8217;être une force pour le marché logiciel, est
|
||
une application du partage. Une démonstration qu&#8217;il est possible de
|
||
travailler ensemble pour fabriquer quelque chose de fonctionnel et
|
||
d&#8217;utile pour tous. Une sorte d&#8217;antithèse de ce modèle capitaliste
|
||
incarné par les brevets&nbsp;logiciel.</p>
|
||
<p>A plusieurs reprises, j&#8217;ai été bluffé par la réalité du logiciel libre.
|
||
Oui, il est facile de collaborer lorsqu&#8217;on crée un logiciel, pour peu
|
||
qu&#8217;on explique les tenants et les aboutissants aux participants. Les
|
||
contributeurs sortent d&#8217;on ne sait où, pour peu que le projet leur soit
|
||
utile. Je ne parle pas d&#8217;outils &#8220;corpo compliant&#8221; (bien que ça soit
|
||
probablement aussi le cas), mais d&#8217;outils que j&#8217;ai pu développer pour
|
||
mon propre usage, et sur lesquels il a été possible de collaborer avec&nbsp;d&#8217;autres.</p>
|
||
<p>Parce que l&#8217;informatique est utile dans bien des milieux, parce qu&#8217;elle
|
||
peut être (et elle l&#8217;est) un vecteur de participation et de
|
||
collaboration, défendons les valeurs qui nous sont chères (logiciels
|
||
libres et ouverts!) et construisons des ponts entre les initiatives qui
|
||
nous parlent (fermes autogérées, initiatives d&#8217;éducation populaire) et&nbsp;l&#8217;informatique.</p>
|
||
<p>Faisons en sorte de rendre l&#8217;informatique accessible et utile dans les
|
||
milieux ou elle peut apporter quelque chose&nbsp;!</p></content><category term="journal"></category></entry><entry><title>How are you handling your shared expenses?</title><link href="https://blog.notmyidea.org/how-are-you-handling-your-shared-expenses.html" rel="alternate"></link><published>2011-10-15T00:00:00+02:00</published><updated>2011-10-15T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-10-15:/how-are-you-handling-your-shared-expenses.html</id><summary type="html">
|
||
<p><strong><span class="caps">TL</span>;<span class="caps">DR</span>:</strong> We&#8217;re kick-starting a new application to manage your shared
|
||
expenses. Have a look at <a href="http://ihatemoney.notmyidea.org">http://ihatemoney.notmyidea.org</a></p>
|
||
<p>As a student, I lived in a lot of different locations, and the majority
|
||
of them had something in common: I lived with others. It usually was a
|
||
great …</p></summary><content type="html">
|
||
<p><strong><span class="caps">TL</span>;<span class="caps">DR</span>:</strong> We&#8217;re kick-starting a new application to manage your shared
|
||
expenses. Have a look at <a href="http://ihatemoney.notmyidea.org">http://ihatemoney.notmyidea.org</a></p>
|
||
<p>As a student, I lived in a lot of different locations, and the majority
|
||
of them had something in common: I lived with others. It usually was a
|
||
great experience (and I think I will continue to live with others). Most
|
||
of the time, we had to spend some time each month to compute who had to
|
||
pay what to the&nbsp;others.</p>
|
||
<p>I wanted to create a pet project using flask, so I wrote a little (\~150
|
||
lines) flask application to handle this. It worked out pretty well for
|
||
my housemates and me, and as we had to move into different locations,
|
||
one of them asked me if he could continue to use it for the year to&nbsp;come.</p>
|
||
<p>I said yes and gave it some more thoughts: We probably aren&#8217;t the only
|
||
ones interested by such kind of software. I decided to extend a bit more
|
||
the software to have a concept of projects and persons (the list of
|
||
persons was hard-coded in the first time,&nbsp;boooh!).</p>
|
||
<p>I then discussed with a friend of mine, who was excited about it and
|
||
wanted to learn python. Great! That&#8217;s a really nice way to get started.
|
||
Some more friends were also interested in it and contributed some
|
||
features and provided feedback (thanks
|
||
<a href="http://www.sneakernet.fr/">Arnaud</a> and&nbsp;Quentin!)</p>
|
||
<p>Since that, the project now support multiple languages and provides a
|
||
<span class="caps">REST</span> <span class="caps">API</span> (android and iphone apps in the tubes!), into other things.
|
||
There is no need to register for an account or whatnot, just enter a
|
||
project name, a secret code and a contact email, invite friends and
|
||
that&#8217;s it (this was inspired by&nbsp;doodle)!</p>
|
||
<p><img alt="Capture d'écran du site." src="/images/ihatemoney.png"></p>
|
||
<p>You can try the project at <a href="http://ihatemoney.notmyidea.org">http://ihatemoney.notmyidea.org</a> for now,
|
||
and the code lives at <a href="https://github.com/spiral-project/ihatemoney/">https://github.com/spiral-project/ihatemoney/</a>.</p>
|
||
<h2 id="features">Features</h2>
|
||
<p>In the wild, currently, there already are some implementations of this
|
||
shared budget manager thing. The fact is that most of them are either
|
||
hard to use, with a too much fancy design or simply trying to do too
|
||
much things at&nbsp;once.</p>
|
||
<p>No, I don&#8217;t want my budget manager to make my shopping list, or to run a
|
||
blog for me, thanks. I want it to let me focus on something else. Keep
|
||
out of my&nbsp;way.</p>
|
||
<h3 id="no-user-registration">No user&nbsp;registration</h3>
|
||
<p>You don&#8217;t need to register an account on the website to start using it.
|
||
You just have to create a project, set a secret code for it, and give
|
||
both the url and the code to the people you want to share it with (or
|
||
the website can poke them for&nbsp;you).</p>
|
||
<h3 id="keeping-things-simple">Keeping things&nbsp;simple</h3>
|
||
<p><span class="dquo">&#8220;</span>Keep It Simple, Stupid&#8221; really matches our philosophy here: you want to
|
||
add a bill? Okay. Just do it. You just have to enter who paid, for who,
|
||
how much, and a description, like you would have done when you&#8217;re back
|
||
from the farmer&#8217;s market on raw&nbsp;paper.</p>
|
||
<h3 id="no-categories">No&nbsp;categories</h3>
|
||
<p>Some people like to organise their stuff into different &#8220;categories&#8221;:
|
||
leisure, work, eating, etc. That&#8217;s not something I want (at least to
|
||
begin&nbsp;with).</p>
|
||
<p>I want things to be simple. Got that? Great. Just add your&nbsp;bills!</p>
|
||
<h3 id="balance">Balance</h3>
|
||
<p>One of the most useful thing is to know what&#8217;s your &#8220;balance&#8221; compared
|
||
to others. In other words, if you&#8217;re negative, you owe money, if you&#8217;re
|
||
positive, you have to receive money. This allows you to dispatch who has
|
||
to pay for the next thing, in order to re-equilibrate the&nbsp;balance.</p>
|
||
<p>Additionally, the system is able to compute for you who has to give how
|
||
much to who, in order to reduce the number of transactions needed to
|
||
restore the&nbsp;balance.</p>
|
||
<h3 id="api"><span class="caps">API</span></h3>
|
||
<p>All of what&#8217;s possible to do with the standard web interface is also
|
||
available through a <span class="caps">REST</span> <span class="caps">API</span>. I developed a simple <span class="caps">REST</span> toolkit for
|
||
flask for this (and I should release&nbsp;it!).</p>
|
||
<h2 id="interested">Interested?</h2>
|
||
<p>This project is open source. All of us like to share what we are doing
|
||
and would be happy to work with new people and implement new ideas. If
|
||
you have a nice idea about this, if you want to tweak it or to fill
|
||
bugs. Don&#8217;t hesitate a second! The project lives at
|
||
<a href="http://github.com/spiral-project/ihatemoney/">http://github.com/spiral-project/ihatemoney/</a></p></content><category term="code"></category></entry><entry><title>La simplicité volontaire contre le mythe de l’abondance</title><link href="https://blog.notmyidea.org/la-simplicite-volontaire-contre-le-mythe-de-labondance.html" rel="alternate"></link><published>2011-10-01T00:00:00+02:00</published><updated>2011-10-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-10-01:/la-simplicite-volontaire-contre-le-mythe-de-labondance.html</id><summary type="html">
|
||
<p>Paul Ariès dans la préface de &#8220;<a href="http://www.editionsladecouverte.fr/catalogue/index.php?ean13=9782707169747">La simplicité volontaire contre le mythe
|
||
de
|
||
l&#8217;abondance</a>&#8221;</p>
|
||
<blockquote>
|
||
<p>Je sais aussi qu&#8217;à force d&#8217;être seulement contre, nous finissons par être « tout contre », tout contre le système, ses débats pourris, ses pratiques immondes, ses perversions mentales. Cessons de porter notre adversaire sur …</p></blockquote></summary><content type="html">
|
||
<p>Paul Ariès dans la préface de &#8220;<a href="http://www.editionsladecouverte.fr/catalogue/index.php?ean13=9782707169747">La simplicité volontaire contre le mythe
|
||
de
|
||
l&#8217;abondance</a>&#8221;</p>
|
||
<blockquote>
|
||
<p>Je sais aussi qu&#8217;à force d&#8217;être seulement contre, nous finissons par être « tout contre », tout contre le système, ses débats pourris, ses pratiques immondes, ses perversions mentales. Cessons de porter notre adversaire sur notre dos, car il finira par nous poignarder, au moment ou nous pensions justement pouvoir le vaincre… Entendons-nous bien, il ne s&#8217;agit pas d&#8217;apprendre à &#8220;positiver&#8221; sous prétexte que l&#8217;on pourrait &#8220;moraliser&#8221; ou repeindre en vert le capitalisme, il s&#8217;agit, bien au contraire, d&#8217;être aussi intraitables lorsque nous créons cet autre monde, que lorsque nous étions ces militants purs mais un peu durs à jouir, il s&#8217;agit d&#8217;être aussi indomptables mais sans oublier que le capitalisme ne pourra être arrêté que par du non-capitaliste… c&#8217;est-à-dire en multipliant les expérimentations sociales, en acceptant de faire au maximum sécession, en inventant (réinventant?) une gauche buissonnière et maquisarde, en faisant, au quotidien, la part belle à la dérive, à des modes de comportement&nbsp;expérimentaux.</p>
|
||
<p>Nous ne devons plus accepter de faire de la politique aux conditions de nos adversaires, car c&#8217;est la seule façon d&#8217;éviter le pessimisme, le ressentiment, une désensibilisation croissante et… la mort&nbsp;lente.</p>
|
||
</blockquote></content><category term="journal"></category></entry><entry><title>Using dbpedia to get languages influences</title><link href="https://blog.notmyidea.org/using-dbpedia-to-get-languages-influences.html" rel="alternate"></link><published>2011-08-16T00:00:00+02:00</published><updated>2011-08-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-08-16:/using-dbpedia-to-get-languages-influences.html</id><summary type="html">
|
||
<p>While browsing the Python&#8217;s wikipedia page, I found information about
|
||
the languages influenced by python, and the languages that influenced
|
||
python&nbsp;itself.</p>
|
||
<p>Well, that&#8217;s kind of interesting to know which languages influenced
|
||
others, it could even be more interesting to have an overview of the
|
||
connexion between them …</p></summary><content type="html">
|
||
<p>While browsing the Python&#8217;s wikipedia page, I found information about
|
||
the languages influenced by python, and the languages that influenced
|
||
python&nbsp;itself.</p>
|
||
<p>Well, that&#8217;s kind of interesting to know which languages influenced
|
||
others, it could even be more interesting to have an overview of the
|
||
connexion between them, keeping python as the main&nbsp;focus.</p>
|
||
<p>This information is available on the wikipedia page, but not in a really
|
||
exploitable format. Hopefully, this information is provided into the
|
||
information box present on the majority of wikipedia pages. And… guess
|
||
what? there is project with the goal to scrap and index all this
|
||
information in a more queriable way, using the semantic web&nbsp;technologies.</p>
|
||
<p>Well, you may have guessed it, the project in question in dbpedia, and
|
||
exposes information in the form of <span class="caps">RDF</span> triples, which are way more easy
|
||
to work with than simple <span class="caps">HTML</span>.</p>
|
||
<p>For instance, let&#8217;s take the page about python:
|
||
<a href="http://dbpedia.org/page/Python_%28programming_language%29">http://dbpedia.org/page/Python_%28programming_language%29</a></p>
|
||
<p>The interesting properties here are &#8220;Influenced&#8221; and &#8220;InfluencedBy&#8221;,
|
||
which allows us to get a list of languages. Unfortunately, they are not
|
||
really using all the power of the Semantic Web here, and the list is
|
||
actually a string with coma separated values in&nbsp;it.</p>
|
||
<p>Anyway, we can use a simple rule: All wikipedia pages of programming
|
||
languages are either named after the name of the language itself, or
|
||
suffixed with &#8220;( programming language)&#8221;, which is the case for&nbsp;python.</p>
|
||
<p>So I&#8217;ve built <a href="https://github.com/ametaireau/experiments/blob/master/influences/get_influences.py">a tiny script to extract the information from
|
||
dbpedia</a>
|
||
and transform them into a shiny graph using&nbsp;graphviz.</p>
|
||
<p>After a&nbsp;nice:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>python<span class="w"> </span>get_influences.py<span class="w"> </span>python<span class="w"> </span>dot<span class="w"> </span><span class="p">|</span><span class="w"> </span>dot<span class="w"> </span>-Tpng<span class="w"> </span>&gt;<span class="w"> </span>influences.png
|
||
</code></pre></div>
|
||
|
||
<p>The result is the following graph (<a href="http://files.lolnet.org/alexis/influences.png">see it directly
|
||
here</a>)</p>
|
||
<p><img alt="Graph des influances des langages les uns sur les
|
||
autres." src="http://files.lolnet.org/alexis/influences.png"></p>
|
||
<p>While reading this diagram, keep in mind that it is a) not listing all
|
||
the languages and b) keeping a python&nbsp;perspective.</p>
|
||
<p>This means that you can trust the scheme by following the arrows from
|
||
python to something and from something to python, it is not trying to
|
||
get the matching between all the languages at the same time to keep
|
||
stuff&nbsp;readable.</p>
|
||
<p>It would certainly be possible to have all the connections between all
|
||
languages (and the resulting script would be easier) to do so, but the
|
||
resulting graph would probably be way less&nbsp;readable.</p>
|
||
<p>You can find the script <a href="https://github.com/ametaireau/experiments">on my github
|
||
account</a>. Feel free to adapt
|
||
it for whatever you want if you feel&nbsp;hackish.</p></content><category term="code"></category></entry><entry><title>Pelican, 9 months later</title><link href="https://blog.notmyidea.org/pelican-9-months-later.html" rel="alternate"></link><published>2011-07-25T00:00:00+02:00</published><updated>2011-07-25T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-07-25:/pelican-9-months-later.html</id><summary type="html">
|
||
<p>Back in October, I released
|
||
<a href="http://docs.notmyidea.org/alexis/pelican">pelican</a>, a little piece of
|
||
code I wrote to power this weblog. I had simple needs: I wanted to be
|
||
able to use my text editor of choice (vim), a vcs (mercurial) and
|
||
restructured text. I started to write a really simple blog engine in …</p></summary><content type="html">
|
||
<p>Back in October, I released
|
||
<a href="http://docs.notmyidea.org/alexis/pelican">pelican</a>, a little piece of
|
||
code I wrote to power this weblog. I had simple needs: I wanted to be
|
||
able to use my text editor of choice (vim), a vcs (mercurial) and
|
||
restructured text. I started to write a really simple blog engine in
|
||
something like a hundred python lines and released it on&nbsp;github.</p>
|
||
<p>And people started contributing. I wasn&#8217;t at all expecting to see people
|
||
interested in such a little piece of code, but it turned out that they
|
||
were. I refactored the code to make it evolve a bit more by two times
|
||
and eventually, in 9 months, got 49 forks, 139 issues and 73 pull&nbsp;requests.</p>
|
||
<p><strong>Which is clearly&nbsp;awesome.</strong></p>
|
||
<p>I pulled features such as translations, tag clouds, integration with
|
||
different services such as twitter or piwik, import from dotclear and
|
||
rss, fixed a number of mistakes and improved a lot the codebase. This
|
||
was a proof that there is a bunch of people that are willing to make
|
||
better softwares just for the sake of&nbsp;fun.</p>
|
||
<p>Thank you, guys, you&#8217;re why I like open source so&nbsp;much.</p></content><category term="code"></category></entry><entry><title>Using JPype to bridge python and Java</title><link href="https://blog.notmyidea.org/using-jpype-to-bridge-python-and-java.html" rel="alternate"></link><published>2011-06-11T00:00:00+02:00</published><updated>2011-06-11T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-06-11:/using-jpype-to-bridge-python-and-java.html</id><summary type="html">
|
||
<p>Java provides some interesting libraries that have no exact equivalent
|
||
in python. In my case, the awesome boilerpipe library allows me to
|
||
remove uninteresting parts of <span class="caps">HTML</span> pages, like menus, footers and other
|
||
&#8220;boilerplate&#8221;&nbsp;contents.</p>
|
||
<p>Boilerpipe is written in Java. Two solutions then: using java from
|
||
python or reimplement boilerpipe …</p></summary><content type="html">
|
||
<p>Java provides some interesting libraries that have no exact equivalent
|
||
in python. In my case, the awesome boilerpipe library allows me to
|
||
remove uninteresting parts of <span class="caps">HTML</span> pages, like menus, footers and other
|
||
&#8220;boilerplate&#8221;&nbsp;contents.</p>
|
||
<p>Boilerpipe is written in Java. Two solutions then: using java from
|
||
python or reimplement boilerpipe in python. I will let you guess which
|
||
one I chosen,&nbsp;meh.</p>
|
||
<p>JPype allows to bridge python project with java libraries. It takes
|
||
another point of view than Jython: rather than reimplementing python in
|
||
Java, both languages are interfacing at the <span class="caps">VM</span> level. This means you
|
||
need to start a <span class="caps">VM</span> from your python script, but it does the job and stay
|
||
fully compatible with Cpython and its C&nbsp;extensions.</p>
|
||
<h2 id="first-steps-with-jpype">First steps with&nbsp;JPype</h2>
|
||
<p>Once JPype installed (you&#8217;ll have to hack a bit some files to integrate
|
||
seamlessly with your system) you can access java classes by doing
|
||
something like&nbsp;that:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">jpype</span>
|
||
<span class="n">jpype</span><span class="o">.</span><span class="n">startJVM</span><span class="p">(</span><span class="n">jpype</span><span class="o">.</span><span class="n">getDefaultJVMPath</span><span class="p">())</span>
|
||
|
||
<span class="c1"># you can then access to the basic java functions</span>
|
||
<span class="n">jpype</span><span class="o">.</span><span class="n">java</span><span class="o">.</span><span class="n">lang</span><span class="o">.</span><span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="s2">&quot;hello world&quot;</span><span class="p">)</span>
|
||
|
||
<span class="c1"># and you have to shutdown the VM at the end</span>
|
||
<span class="n">jpype</span><span class="o">.</span><span class="n">shutdownJVM</span><span class="p">()</span>
|
||
</code></pre></div>
|
||
|
||
<p>Okay, now we have a hello world, but what we want seems somehow more
|
||
complex. We want to interact with java classes, so we will have to load&nbsp;them.</p>
|
||
<h2 id="interfacing-with-boilerpipe">Interfacing with&nbsp;Boilerpipe</h2>
|
||
<p>To install boilerpipe, you just have to run an ant&nbsp;script:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span><span class="nb">cd</span><span class="w"> </span>boilerpipe
|
||
$<span class="w"> </span>ant
|
||
</code></pre></div>
|
||
|
||
<p>Here is a simple example of how to use boilerpipe in Java, from their&nbsp;sources</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">package</span><span class="w"> </span><span class="nn">de.l3s.boilerpipe.demo</span><span class="p">;</span>
|
||
<span class="kn">import</span><span class="w"> </span><span class="nn">java.net.URL</span><span class="p">;</span>
|
||
<span class="kn">import</span><span class="w"> </span><span class="nn">de.l3s.boilerpipe.extractors.ArticleExtractor</span><span class="p">;</span>
|
||
|
||
<span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">Oneliner</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="kd">final</span><span class="w"> </span><span class="n">String</span><span class="o">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="kd">throws</span><span class="w"> </span><span class="n">Exception</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">URL</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">URL</span><span class="p">(</span><span class="s">&quot;http://notmyidea.org&quot;</span><span class="p">);</span>
|
||
<span class="w"> </span><span class="n">System</span><span class="p">.</span><span class="na">out</span><span class="p">.</span><span class="na">println</span><span class="p">(</span><span class="n">ArticleExtractor</span><span class="p">.</span><span class="na">INSTANCE</span><span class="p">.</span><span class="na">getText</span><span class="p">(</span><span class="n">url</span><span class="p">));</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>To run&nbsp;it:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>javac<span class="w"> </span>-cp<span class="w"> </span>dist/boilerpipe-1.1-dev.jar:lib/nekohtml-1.9.13.jar:lib/xerces-2.9.1.jar<span class="w"> </span>src/demo/de/l3s/boilerpipe/demo/Oneliner.java
|
||
$<span class="w"> </span>java<span class="w"> </span>-cp<span class="w"> </span>src/demo:dist/boilerpipe-1.1-dev.jar:lib/nekohtml-1.9.13.jar:lib/xerces-2.9.1.jar<span class="w"> </span>de.l3s.boilerpipe.demo.Oneliner
|
||
</code></pre></div>
|
||
|
||
<p>Yes, this is kind of ugly, sorry for your eyes. Let&#8217;s try something
|
||
similar, but from&nbsp;python</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">jpype</span>
|
||
|
||
<span class="c1"># start the JVM with the good classpaths</span>
|
||
<span class="n">classpath</span> <span class="o">=</span> <span class="s2">&quot;dist/boilerpipe-1.1-dev.jar:lib/nekohtml-1.9.13.jar:lib/xerces-2.9.1.jar&quot;</span>
|
||
<span class="n">jpype</span><span class="o">.</span><span class="n">startJVM</span><span class="p">(</span><span class="n">jpype</span><span class="o">.</span><span class="n">getDefaultJVMPath</span><span class="p">(),</span> <span class="s2">&quot;-Djava.class.path=</span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">classpath</span><span class="p">)</span>
|
||
|
||
<span class="c1"># get the Java classes we want to use</span>
|
||
<span class="n">DefaultExtractor</span> <span class="o">=</span> <span class="n">jpype</span><span class="o">.</span><span class="n">JPackage</span><span class="p">(</span><span class="s2">&quot;de&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">l3s</span><span class="o">.</span><span class="n">boilerpipe</span><span class="o">.</span><span class="n">extractors</span><span class="o">.</span><span class="n">DefaultExtractor</span>
|
||
|
||
<span class="c1"># call them !</span>
|
||
<span class="nb">print</span> <span class="n">DefaultExtractor</span><span class="o">.</span><span class="n">INSTANCE</span><span class="o">.</span><span class="n">getText</span><span class="p">(</span><span class="n">jpype</span><span class="o">.</span><span class="n">java</span><span class="o">.</span><span class="n">net</span><span class="o">.</span><span class="n">URL</span><span class="p">(</span><span class="s2">&quot;http://blog.notmyidea.org&quot;</span><span class="p">))</span>
|
||
</code></pre></div>
|
||
|
||
<p>And you get what you&nbsp;want.</p>
|
||
<p>I must say I didn&#8217;t thought it could work so easily. This will allow me
|
||
to extract text content from URLs and remove the <em>boilerplate</em> text
|
||
easily for infuse (my master thesis project), without having to write
|
||
java code,&nbsp;nice!</p></content><category term="code"></category></entry><entry><title>Un coup de main pour mon mémoire !</title><link href="https://blog.notmyidea.org/un-coup-de-main-pour-mon-memoire.html" rel="alternate"></link><published>2011-05-25T00:00:00+02:00</published><updated>2011-05-25T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-05-25:/un-coup-de-main-pour-mon-memoire.html</id><summary type="html">
|
||
<p>Ça y est, bientôt la fin. <span class="caps">LA</span> <span class="caps">FIN</span>. La fin des études, et le début du
|
||
reste. En attendant je bosse sur mon mémoire de fin d&#8217;études et j&#8217;aurais
|
||
besoin d&#8217;un petit coup de&nbsp;main.</p>
|
||
<p>Mon mémoire porte sur les systèmes de recommandation. Pour ceux qui
|
||
connaissent …</p></summary><content type="html">
|
||
<p>Ça y est, bientôt la fin. <span class="caps">LA</span> <span class="caps">FIN</span>. La fin des études, et le début du
|
||
reste. En attendant je bosse sur mon mémoire de fin d&#8217;études et j&#8217;aurais
|
||
besoin d&#8217;un petit coup de&nbsp;main.</p>
|
||
<p>Mon mémoire porte sur les systèmes de recommandation. Pour ceux qui
|
||
connaissent last.fm, je fais quelque chose de similaire mais pour les
|
||
sites internet: en me basant sur ce que vous visitez quotidiennement et
|
||
comment vous le visitez (quelles horaires, quelle emplacement
|
||
géographique, etc.) je souhaites proposer des liens qui vous
|
||
intéresseront potentiellement, en me basant sur l&#8217;avis des personnes
|
||
qui ont des profils similaires au&nbsp;votre.</p>
|
||
<p>Le projet est loin d&#8217;être terminé, mais la première étape est de
|
||
récupérer des données de navigation, idéalement beaucoup de données de
|
||
navigation. Donc si vous pouvez me filer un coup de main je vous en
|
||
serais éternellement reconnaissant (pour ceux qui font semblant de pas
|
||
comprendre, entendez &#8220;tournée&nbsp;générale&#8221;).</p>
|
||
<p>J&#8217;ai créé un petit site web (en anglais) qui résume un peu le concept,
|
||
qui vous propose de vous inscrire et de télécharger un plugin firefox
|
||
qui m&#8217;enverra des information sur les sites que vous visitez (si vous
|
||
avez l&#8217;habitude d&#8217;utiliser chrome vous pouvez considérer de switcher à
|
||
firefox4 pour les deux prochains mois pour me filer un coup de main). Il
|
||
est possible de désactiver le plugin d&#8217;un simple clic si vous souhaitez
|
||
garder votre vie privée privée&nbsp;;-)</p>
|
||
<p>Le site est par là: <a href="http://infuse.notmyidea.org">http://infuse.notmyidea.org</a>. Une fois le plugin
|
||
téléchargé et le compte créé il faut renseigner vos identifiants dans
|
||
le plugin en question, et c&#8217;est&nbsp;tout!</p>
|
||
<p>A votre bon cœur ! Je récupérerais probablement des données durant les
|
||
2 prochains mois pour ensuite les analyser&nbsp;correctement.</p>
|
||
<p>Merci pour votre aide&nbsp;!</p></content><category term="code"></category></entry><entry><title>Travailler moins pour mieux travailler ?</title><link href="https://blog.notmyidea.org/travailler-moins-pour-mieux-travailler.html" rel="alternate"></link><published>2011-05-19T00:00:00+02:00</published><updated>2011-05-19T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-05-19:/travailler-moins-pour-mieux-travailler.html</id><summary type="html">
|
||
<p>Je viens de passer une semaine et demi quasiment hors-ligne et je dois
|
||
dire que je suis assez impressionné du résultat: je suis de retour chez
|
||
mes parents pour le &#8220;easter break&#8221; et j&#8217;en ai profité pour donner un
|
||
coup aux travaux de la maison (et pour me reposer …</p></summary><content type="html">
|
||
<p>Je viens de passer une semaine et demi quasiment hors-ligne et je dois
|
||
dire que je suis assez impressionné du résultat: je suis de retour chez
|
||
mes parents pour le &#8220;easter break&#8221; et j&#8217;en ai profité pour donner un
|
||
coup aux travaux de la maison (et pour me reposer un&nbsp;brin!).</p>
|
||
<p>Bosser en extérieur est un réel plaisir et faire quelque chose de manuel
|
||
également. Je n&#8217;ai pas pour habitude de bricoler autre chose que du
|
||
logiciel et c&#8217;est vraiment quelque chose que&nbsp;j&#8217;apprécie.</p>
|
||
<p>J&#8217;avoue, je mens un peu quand je dis que j&#8217;étais complètement
|
||
déconnecté: j&#8217;ai vérifié mes mails assez régulièrement en utilisant
|
||
mon téléphone (merci Arnaud pour le prêt du gadget!) et j&#8217;ai limité ma
|
||
présence web au strict minimum. Je veux dire par là pas de twitter, pas
|
||
d&#8217;<span class="caps">IRC</span> et autres&nbsp;mailing-lists.</p>
|
||
<p>Quand je dis hors-ligne, je ne dis pas que je n&#8217;ai pas travaillé sur mon
|
||
ordinateur. J&#8217;ai à fournir beaucoup plus de travail que ce que je ne
|
||
pensait en premier lieu pour la rédaction de mon mémoire et j&#8217;ai passé
|
||
quelques heures par ci par là à lire des articles et livres sur le sujet
|
||
ainsi que rédigé une bonne partie de mon mémoire durant ces 10 jours.
|
||
Résultat ? Les heures que j&#8217;ai passées à travailler ont été étonnement
|
||
plus productives que celles que j&#8217;ai l&#8217;habitude de passer derrière un
|
||
écran. Je ne parles pas uniquement du fait de procrastiner; évidemment
|
||
c&#8217;est une des causes principales de ma perte de productivité, mais je
|
||
pense également au fait de laisser le cerveau reposer, au moins en ce
|
||
qui concerne la partie informatique. Bricoler demande de la
|
||
concentration et de la réflexion mais permet également de laisser son
|
||
esprit vagabonder. J&#8217;ai pu donc avancer mes sur certaines parties de mon
|
||
mémoire alors que j&#8217;étais en train de poser le bardage sur la garage par&nbsp;exemple.</p>
|
||
<p>Passer du temps sur autre chose (qui demandait également de la
|
||
concentration par ailleurs) m&#8217;a permis d&#8217;être réellement plus efficace
|
||
lors de mes phases de rédaction et de&nbsp;lecture.</p>
|
||
<p>Je me demande depuis quelques temps quel sera mon futur travail et
|
||
quelle forme il prendra. Éééh oui, la fin des études arrive pour la fin
|
||
de l&#8217;année, c&#8217;est pas une blague. Et je me pose sérieusement la question
|
||
du travail aux 3/4 temps. La raison principale étant que je ne souhaites
|
||
pas passer la majeure partie de mon temps à travailler derrière un écran
|
||
et que la formation que j&#8217;ai m&#8217;y rattache beaucoup. Ne me comprenez pas
|
||
de travers: j&#8217;aime ce que je fais; mais j&#8217;aime aussi ce que je fais à
|
||
coté de l&#8217;informatique: associatif, projets alternatifs, permaculture et&nbsp;autres.</p>
|
||
<p>Viens s&#8217;ajouter à ça le fait d&#8217;avoir une qualité de vie qui me semble
|
||
pouvoir passer par le fait de travailler moins (&#8220;il est marant ce gamin,
|
||
il à pas encore commencé à travailler qu&#8217;il veut bosser moins, regarde
|
||
moi cette feignasse!&#8221;) et travailler plus efficacement. Bien sur, on
|
||
n&#8217;est jamais 100% productif et c&#8217;est d&#8217;autant plus vrai pour moi, alors
|
||
si gagner en productivité peut passer par travailler moins, pourquoi pas
|
||
s&#8217;y essayer&nbsp;!</p>
|
||
<p>Peut être que vous pratiquez déjà le travail au 3/4 temps, que vous avez
|
||
des retours d&#8217;expérience à faire : fausse bonne idée ? Vraie bonne idée&nbsp;?</p></content><category term="journal"></category></entry><entry><title>Analyse users’ browsing context to build up a web recommender</title><link href="https://blog.notmyidea.org/analyse-users-browsing-context-to-build-up-a-web-recommender.html" rel="alternate"></link><published>2011-04-01T00:00:00+02:00</published><updated>2011-04-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-04-01:/analyse-users-browsing-context-to-build-up-a-web-recommender.html</id><summary type="html">
|
||
<p>No, this is not an april&#8217;s fool&nbsp;;)</p>
|
||
<p>Wow, it&#8217;s been a long time. My year in Oxford is going really well. I
|
||
realized few days ago that the end of the year is approaching really
|
||
quickly. Exams are coming in one month or such and then I&#8217;ll …</p></summary><content type="html">
|
||
<p>No, this is not an april&#8217;s fool&nbsp;;)</p>
|
||
<p>Wow, it&#8217;s been a long time. My year in Oxford is going really well. I
|
||
realized few days ago that the end of the year is approaching really
|
||
quickly. Exams are coming in one month or such and then I&#8217;ll be working
|
||
full time on my dissertation&nbsp;topic.</p>
|
||
<p>When I learned we&#8217;ll have about 6 month to work on something, I first
|
||
thought about doing a packaging related stuff, but finally decided to
|
||
start something new. After all, that&#8217;s the good time to&nbsp;learn.</p>
|
||
<p>Since a long time, I&#8217;m being impressed by the <a href="http://last.fm">last.fm</a>
|
||
recommender system. They&#8217;re <em>scrobbling</em> the music I listen to since
|
||
something like 5 years now and the recommendations they&#8217;re doing are
|
||
really nice and accurate (I discovered <strong>a lot</strong> of great artists
|
||
listening to the &#8220;neighbour radio&#8221;.) (by the way, <a href="http://lastfm.com/user/akounet/">here
|
||
is</a> my lastfm&nbsp;account)</p>
|
||
<p>So I decided to work on recommender systems, to better understand what
|
||
is it&nbsp;about.</p>
|
||
<p>Recommender systems are usually used to increase the sales of products
|
||
(like Amazon.com does) which is not really what I&#8217;m looking for (The one
|
||
who know me a bit know I&#8217;m kind of sick about all this consumerism going&nbsp;on).</p>
|
||
<p>Actually, the most simple thing I thought of was the web: I&#8217;m browsing
|
||
it quite every day and each time new content appears. I&#8217;ve stopped to
|
||
follow <a href="https://bitbucket.org/bruno/aspirator/">my feed reader</a> because
|
||
of the information overload, and reduced drastically the number of
|
||
people I follow <a href="http://twitter.com/ametaireau/">on twitter</a>.</p>
|
||
<p>Too much information kills the&nbsp;information.</p>
|
||
<p>You shall got what will be my dissertation topic: a recommender system
|
||
for the web. Well, such recommender systems already exists, so I will
|
||
try to add contextual information to them: you&#8217;re probably not
|
||
interested by the same topics at different times of the day, or
|
||
depending on the computer you&#8217;re using. We can also probably make good
|
||
use of the way you browse to create groups into the content you&#8217;re
|
||
browsing (or even use the great firefox4 tab group&nbsp;feature).</p>
|
||
<p>There is a large part of concerns to have about user&#8217;s privacy as&nbsp;well.</p>
|
||
<p>Here is my proposal (copy/pasted from the one I had to do for my&nbsp;master)</p>
|
||
<h2 id="introduction-and-rationale">Introduction and&nbsp;rationale</h2>
|
||
<p>Nowadays, people surf the web more and more often. New web pages are
|
||
created each day so the amount of information to retrieve is more
|
||
important as the time passes. These users uses the web in different
|
||
contexts, from finding cooking recipes to technical&nbsp;articles.</p>
|
||
<p>A lot of people share the same interest to various topics, and the
|
||
quantity of information is such than it&#8217;s really hard to triage them
|
||
efficiently without spending hours doing it. Firstly because of the huge
|
||
quantity of information but also because the triage is something
|
||
relative to each person. Although, this triage can be facilitated by
|
||
fetching the browsing information of all particular individuals and put
|
||
the in&nbsp;perspective.</p>
|
||
<p>Machine learning is a branch of Artificial Intelligence (<span class="caps">AI</span>) which deals
|
||
with how a program can learn from data. Recommendation systems are a
|
||
particular application area of machine learning which is able to
|
||
recommend things (links in our case) to the users, given a particular
|
||
database containing the previous choices users have&nbsp;made.</p>
|
||
<p>This browsing information is currently available in browsers. Even if it
|
||
is not in a very usable format, it is possible to transform it to
|
||
something useful. This information gold mine just wait to be used.
|
||
Although, it is not as simple as it can seems at the first approach: It
|
||
is important to take care of the context the user is in while browsing
|
||
links. For instance, It&#8217;s more likely that during the day, a computer
|
||
scientist will browse computing related links, and that during the
|
||
evening, he browse cooking recipes or something&nbsp;else.</p>
|
||
<p>Page contents are also interesting to analyse, because that&#8217;s what
|
||
people browse and what actually contain the most interesting part of the
|
||
information. The raw data extracted from the browsing can then be
|
||
translated into something more useful (namely tags, type of resource,
|
||
visit frequency, navigation context&nbsp;etc.)</p>
|
||
<p>The goal of this dissertation is to create a recommender system for web
|
||
links, including this context&nbsp;information.</p>
|
||
<p>At the end of the dissertation, different pieces of software will be
|
||
provided, from raw data collection from the browser to a recommendation&nbsp;system.</p>
|
||
<h2 id="background-review">Background&nbsp;Review</h2>
|
||
<p>This dissertation is mainly about data extraction, analysis and
|
||
recommendation systems. Two different research area can be isolated:
|
||
Data preprocessing and Information&nbsp;filtering.</p>
|
||
<p>The first step in order to make recommendations is to gather some data.
|
||
The more data we have available, the better it is (T. Segaran, 2007).
|
||
This data can be retrieved in various ways, one of them is to get it
|
||
directly from user&#8217;s&nbsp;browsers.</p>
|
||
<h3 id="data-preparation-and-extraction">Data preparation and&nbsp;extraction</h3>
|
||
<p>The data gathered from browsers is basically URLs and additional
|
||
information about the context of the navigation. There is clearly a need
|
||
to extract more information about the meaning of the data the user is
|
||
browsing, starting by the content of the web&nbsp;pages.</p>
|
||
<p>Because the information provided on the current Web is not meant to be
|
||
read by machines (T. Berners Lee, 2001) there is a need of tools to
|
||
extract meaning from web pages. The information needs to be preprocessed
|
||
before stored in a machine readable format, allowing to make
|
||
recommendations (Choochart et Al,&nbsp;2004).</p>
|
||
<p>Data preparation is composed of two steps: cleaning and structuring (
|
||
Castellano et Al, 2007). Because raw data can contain a lot of un-needed
|
||
text (such as menus, headers etc.) and need to be cleaned prior to be
|
||
stored. Multiple techniques can be used here and belongs to boilerplate
|
||
removal and full text extraction (Kohlschütter et Al,&nbsp;2010).</p>
|
||
<p>Then, structuring the information: category, type of content (news,
|
||
blog, wiki) can be extracted from raw data. This kind of information is
|
||
not clearly defined by <span class="caps">HTML</span> pages so there is a need of tools to
|
||
recognise&nbsp;them.</p>
|
||
<p>Some context-related information can also be inferred from each
|
||
resource. It can go from the visit frequency to the navigation group the
|
||
user was in while browsing. It is also possible to determine if the user
|
||
&#8220;liked&#8221; a resource, and determine a mark for it, which can be used by
|
||
information filtering a later step (T. Segaran,&nbsp;2007).</p>
|
||
<p>At this stage, structuring the data is required. Storing this kind of
|
||
information in <span class="caps">RDBMS</span> can be a bit tedious and require complex queries to
|
||
get back the data in an usable format. Graph databases can play a major
|
||
role in the simplification of information storage and&nbsp;querying.</p>
|
||
<h3 id="information-filtering">Information&nbsp;filtering</h3>
|
||
<p>To filter the information, three techniques can be used (Balabanovic et
|
||
Al,&nbsp;1997):</p>
|
||
<ul>
|
||
<li>The content-based approach states that if an user have liked
|
||
something in the past, he is more likely to like similar things in
|
||
the future. So it&#8217;s about establishing a profile for the user and
|
||
compare new items against&nbsp;it.</li>
|
||
<li>The collaborative approach will rather recommend items that other
|
||
similar users have liked. This approach consider only the
|
||
relationship between users, and not the profile of the user we are
|
||
making recommendations&nbsp;to.</li>
|
||
<li>the hybrid approach, which appeared recently combine both of the
|
||
previous approaches, giving recommendations when items score high
|
||
regarding user&#8217;s profile, or if a similar user already liked&nbsp;it.</li>
|
||
</ul>
|
||
<p>Grouping is also something to consider at this stage (G. Myatt, 2007).
|
||
Because we are dealing with huge amount of data, it can be useful to
|
||
detect group of data that can fit together. Data clustering is able to
|
||
find such groups (T. Segaran,&nbsp;2007).</p>
|
||
<p>References:</p>
|
||
<ul>
|
||
<li>Balabanović, M., <span class="amp">&amp;</span> Shoham, Y. (1997). Fab: content-based,
|
||
collaborative recommendation. Communications of the <span class="caps">ACM</span>, 40(3),
|
||
66–72. <span class="caps">ACM</span>. Retrieved March 1, 2011, from
|
||
<a href="http://portal.acm.org/citation.cfm?id=245108.245124&amp;">http://portal.acm.org/citation.cfm?id=245108.245124&amp;</a>;.</li>
|
||
<li>Berners-Lee, T., Hendler, J., <span class="amp">&amp;</span> Lassila, O. (2001). The semantic
|
||
web: Scientific american. Scientific American, 284(5), 34–43.
|
||
Retrieved November 21, 2010, from
|
||
<a href="http://www.citeulike.org/group/222/article/1176986">http://www.citeulike.org/group/222/article/1176986</a>.</li>
|
||
<li>Castellano, G., Fanelli, A., <span class="amp">&amp;</span> Torsello, M. (2007). <span class="caps">LODAP</span>: a LOg
|
||
DAta Preprocessor for mining Web browsing patterns. Proceedings of
|
||
the 6th Conference on 6th <span class="caps">WSEAS</span> Int. Conf. on Artificial
|
||
Intelligence, Knowledge Engineering and Data Bases-Volume 6 (p.
|
||
12–17). World Scientific and Engineering Academy and Society
|
||
(<span class="caps">WSEAS</span>). Retrieved March 8, 2011, from
|
||
<a href="http://portal.acm.org/citation.cfm?id=1348485.1348488">http://portal.acm.org/citation.cfm?id=1348485.1348488</a>.</li>
|
||
<li>Kohlschutter, C., Fankhauser, P., <span class="amp">&amp;</span> Nejdl, W. (2010). Boilerplate
|
||
detection using shallow text features. Proceedings of the third <span class="caps">ACM</span>
|
||
international conference on Web search and data mining (p. 441–450).
|
||
<span class="caps">ACM</span>. Retrieved March 8, 2011, from
|
||
<a href="http://portal.acm.org/citation.cfm?id=1718542">http://portal.acm.org/citation.cfm?id=1718542</a>.</li>
|
||
<li>Myatt, <span class="caps">G. J.</span>(2007). Making Sense of Data: A Practical Guide to
|
||
Exploratory Data Analysis and Data&nbsp;Mining.</li>
|
||
<li>Segaran, T. (2007). Collective&nbsp;Intelligence.</li>
|
||
</ul>
|
||
<h2 id="privacy">Privacy</h2>
|
||
<p>The first thing that&#8217;s come to people minds when it comes to process
|
||
their browsing data is privacy. People don&#8217;t want to be stalked. That&#8217;s
|
||
perfectly right, and I don&#8217;t&nbsp;either.</p>
|
||
<p>But such a system don&#8217;t have to deal with people identities. It&#8217;s
|
||
completely possible to process completely anonymous data, and that&#8217;s
|
||
probably what I&#8217;m gonna&nbsp;do.</p>
|
||
<p>By the way, if you have interesting thoughts about that, if you do know
|
||
projects that do seems related, fire the comments&nbsp;!</p>
|
||
<h2 id="whats-the-plan">What&#8217;s the plan&nbsp;?</h2>
|
||
<p>There is a lot of different things to explore, especially because I&#8217;m a
|
||
complete novice in that&nbsp;field.</p>
|
||
<ul>
|
||
<li>I want to develop a firefox plugin, to extract the browsing
|
||
informations ( still, I need to know exactly which kind of
|
||
informations to retrieve). The idea is to provide some <em>raw</em>
|
||
browsing data, and then to transform it and to store it in the
|
||
better possible&nbsp;way.</li>
|
||
<li>Analyse how to store the informations in a graph database. What can
|
||
be the different methods to store this data and to visualize the
|
||
relationship between different pieces of data? How can I define the
|
||
different contexts, and add those informations in the&nbsp;db?</li>
|
||
<li>Process the data using well known recommendation algorithms. Compare
|
||
the results and criticize their&nbsp;value.</li>
|
||
</ul>
|
||
<p>There is plenty of stuff I want to try during this&nbsp;experimentation:</p>
|
||
<ul>
|
||
<li>I want to try using Geshi to visualize the connexion between the
|
||
links, and the&nbsp;contexts</li>
|
||
<li>Try using graph databases such as&nbsp;Neo4j</li>
|
||
<li>Having a deeper look at tools such as scikit.learn (a machine
|
||
learning toolkit in&nbsp;python)</li>
|
||
<li>Analyse web pages in order to categorize them. Processing their
|
||
contents as well, to do some keyword based classification will be&nbsp;done.</li>
|
||
</ul>
|
||
<p>Lot of work on its way, yay&nbsp;!</p></content><category term="code"></category></entry><entry><title>Working directly on your server? How to backup and sync your dev environment with unison</title><link href="https://blog.notmyidea.org/working-directly-on-your-server-how-to-backup-and-sync-your-dev-environment-with-unison.html" rel="alternate"></link><published>2011-03-16T00:00:00+01:00</published><updated>2011-03-16T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-03-16:/working-directly-on-your-server-how-to-backup-and-sync-your-dev-environment-with-unison.html</id><summary type="html">
|
||
<p>I have a server running freebsd since some time now, and was wondering
|
||
about the possibility to directly have a development environment ready
|
||
to use when I get a internet connexion, even if I&#8217;m not on my&nbsp;computer.</p>
|
||
<p>Since I use vim to code, and spend most of my …</p></summary><content type="html">
|
||
<p>I have a server running freebsd since some time now, and was wondering
|
||
about the possibility to directly have a development environment ready
|
||
to use when I get a internet connexion, even if I&#8217;m not on my&nbsp;computer.</p>
|
||
<p>Since I use vim to code, and spend most of my time in a console while
|
||
developing, it&#8217;s possible to work via ssh, from&nbsp;everywhere.</p>
|
||
<p>The only problem is the synchronisation of the source code, config files
|
||
etc. from my machine to the&nbsp;server.</p>
|
||
<p>Unison provides an interesting way to synchronise two folders, even over
|
||
a network. So let&#8217;s do it&nbsp;!</p>
|
||
<h2 id="creating-the-jail">Creating the&nbsp;jail</h2>
|
||
<p>In case you don&#8217;t use FreeBSD, you can skip this&nbsp;section.</p>
|
||
<div class="highlight"><pre><span></span><code># I have a flavour jail named default
|
||
$ ezjail-admin -f default workspace.notmyidea.org 172.19.1.6
|
||
$ ezjail-admin start workspace.notmyidea.org
|
||
</code></pre></div>
|
||
|
||
<p>In my case, because the &#8220;default&#8221; flavour contains already a lot of
|
||
interesting things, my jail come already setup with ssh, bash and vim
|
||
for instance, but maybe you&#8217;ll need it in your&nbsp;case.</p>
|
||
<p>I want to be redirected to the ssh of the jail when I connect to the
|
||
host with the 20006 port. Add lines in <code>/etc/pf.conf</code>:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="nv">workspace_jail</span><span class="o">=</span><span class="s2">&quot;172.19.1.6&quot;</span>
|
||
<span class="w"> </span>rdr<span class="w"> </span>on<span class="w"> </span><span class="nv">$ext_if</span><span class="w"> </span>proto<span class="w"> </span>tcp<span class="w"> </span>from<span class="w"> </span>any<span class="w"> </span>to<span class="w"> </span><span class="nv">$ext_ip</span><span class="w"> </span>port<span class="w"> </span><span class="m">20006</span><span class="w"> </span>-&gt;<span class="w"> </span><span class="nv">$workspace_jail</span><span class="w"> </span>port<span class="w"> </span><span class="m">22</span>
|
||
</code></pre></div>
|
||
|
||
<p>Reload packet filter&nbsp;rules</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>/etc/rc.d/pf<span class="w"> </span>reload
|
||
</code></pre></div>
|
||
|
||
<h2 id="working-with-unison">Working with&nbsp;unison</h2>
|
||
<p>Now that we&#8217;ve set up the jail. Set up unison on the server and on your
|
||
client. Unison is available on the freebsd ports so just install&nbsp;it</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ssh<span class="w"> </span>notmyidea.org<span class="w"> </span>-p<span class="w"> </span><span class="m">20006</span>
|
||
$<span class="w"> </span>make<span class="w"> </span>-C<span class="w"> </span>/usr/ports/net/unison-nox11<span class="w"> </span>config-recursive
|
||
$<span class="w"> </span>make<span class="w"> </span>-C<span class="w"> </span>/usr/ports/net/unison-nox11<span class="w"> </span>package-recursive
|
||
</code></pre></div>
|
||
|
||
<p>Install as well unison on your local machine. Double check to install
|
||
the same version on the client and on the server. Ubuntu contains the
|
||
2.27.57 as well as the&nbsp;2.32.52.</p>
|
||
<p>Check that unison is installed and reachable via ssh from your&nbsp;machine</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>ssh<span class="w"> </span>notmyidea.org<span class="w"> </span>-p<span class="w"> </span><span class="m">20006</span><span class="w"> </span>unison<span class="w"> </span>-version
|
||
unison<span class="w"> </span>version<span class="w"> </span><span class="m">2</span>.27.157
|
||
$<span class="w"> </span>unison<span class="w"> </span>-version
|
||
unison<span class="w"> </span>version<span class="w"> </span><span class="m">2</span>.27.57
|
||
</code></pre></div>
|
||
|
||
<h2 id="let-sync-our-folders">Let sync our&nbsp;folders</h2>
|
||
<p>The first thing I want to sync is my vim configuration. Well, it&#8217;s
|
||
already <a href="http://github.com/ametaireau/dotfiles/">in a git repository</a>
|
||
but let&#8217;s try to use unison for it right&nbsp;now.</p>
|
||
<p>I have two machines then: workspace, the jail, and ecureuil my&nbsp;laptop.</p>
|
||
<div class="highlight"><pre><span></span><code>unison<span class="w"> </span>.vim<span class="w"> </span>ssh://notmyidea.org:20006/.vim
|
||
unison<span class="w"> </span>.vimrc<span class="w"> </span>ssh://notmyidea.org:20006/.vimrc
|
||
</code></pre></div>
|
||
|
||
<p>It is also possible to put all the informations in a config file, and
|
||
then to only run unison. (fire up vim&nbsp;\~/.unison/default.prf.</p>
|
||
<p>Here is my&nbsp;config:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="w"> </span><span class="na">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">/home/alexis</span>
|
||
<span class="w"> </span><span class="na">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">ssh://notmyidea.org:20006</span>
|
||
|
||
<span class="w"> </span><span class="na">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">.vimrc</span>
|
||
<span class="w"> </span><span class="na">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">dotfiles</span>
|
||
<span class="w"> </span><span class="na">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">dev</span>
|
||
|
||
<span class="w"> </span><span class="na">follow</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">Name *</span>
|
||
</code></pre></div>
|
||
|
||
<p>My vimrc is in fact a symbolic link on my laptop, but I don&#8217;t want to
|
||
specify each of the links to unison. That&#8217;s why the follow = Name * is&nbsp;for.</p>
|
||
<p>The folders you want to synchronize are maybe a bit large. If so,
|
||
considering others options such as rsync for the first import may be a
|
||
good idea (I enjoyed my university huge upload bandwith to upload <span class="caps">2GB</span> in
|
||
20mn&nbsp;;)</p>
|
||
<h2 id="run-the-script-frequently">Run the script&nbsp;frequently</h2>
|
||
<p>Once that done, you just need to run the unison command line some times
|
||
when you want to sync your two machines. I&#8217;ve wrote a tiny script to get
|
||
some feedback from the&nbsp;sync:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">os</span>
|
||
<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
|
||
|
||
<span class="n">DEFAULT_LOGFILE</span> <span class="o">=</span> <span class="s2">&quot;~/unison.log&quot;</span>
|
||
<span class="n">PROGRAM_NAME</span> <span class="o">=</span> <span class="s2">&quot;Unison syncer&quot;</span>
|
||
|
||
<span class="k">def</span> <span class="nf">sync</span><span class="p">(</span><span class="n">logfile</span><span class="o">=</span><span class="n">DEFAULT_LOGFILE</span><span class="p">,</span> <span class="n">program_name</span><span class="o">=</span><span class="n">PROGRAM_NAME</span><span class="p">):</span>
|
||
<span class="c1"># init</span>
|
||
<span class="n">display_message</span> <span class="o">=</span> <span class="kc">True</span>
|
||
<span class="n">error</span> <span class="o">=</span> <span class="kc">False</span>
|
||
|
||
<span class="n">before</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
|
||
<span class="c1"># call unison to make the sync</span>
|
||
<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#39;unison -batch &gt; </span><span class="si">{0}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">logfile</span><span class="p">))</span>
|
||
|
||
<span class="c1"># get the duration of the operation</span>
|
||
<span class="n">td</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span> <span class="o">-</span> <span class="n">before</span>
|
||
<span class="n">delta</span> <span class="o">=</span> <span class="p">(</span><span class="n">td</span><span class="o">.</span><span class="n">microseconds</span> <span class="o">+</span> <span class="p">(</span><span class="n">td</span><span class="o">.</span><span class="n">seconds</span> <span class="o">+</span> <span class="n">td</span><span class="o">.</span><span class="n">days</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">3600</span><span class="p">)</span> <span class="o">*</span> <span class="mi">10</span><span class="o">**</span><span class="mi">6</span><span class="p">)</span> <span class="o">/</span> <span class="mi">10</span><span class="o">**</span><span class="mi">6</span>
|
||
|
||
<span class="c1"># check what was the last entry in the log</span>
|
||
<span class="n">log</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="n">logfile</span><span class="p">))</span>
|
||
<span class="n">lines</span> <span class="o">=</span> <span class="n">log</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
|
||
<span class="k">if</span> <span class="s1">&#39;No updates to propagate&#39;</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
|
||
<span class="n">display_message</span> <span class="o">=</span> <span class="kc">False</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="n">l</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">lines</span> <span class="k">if</span> <span class="s2">&quot;Synchronization&quot;</span> <span class="ow">in</span> <span class="n">l</span><span class="p">]</span>
|
||
|
||
<span class="n">message</span> <span class="o">=</span> <span class="n">output</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="n">message</span> <span class="o">+=</span> <span class="s2">&quot; It took </span><span class="si">{0}</span><span class="s2">s.&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">delta</span><span class="p">)</span>
|
||
|
||
<span class="k">if</span> <span class="n">display_message</span><span class="p">:</span>
|
||
<span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="s1">&#39;notify-send -i </span><span class="si">{2}</span><span class="s1"> &quot;</span><span class="si">{0}</span><span class="s1">&quot; &quot;</span><span class="si">{1}</span><span class="s1">&quot;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">program_name</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span>
|
||
<span class="s1">&#39;error&#39;</span> <span class="k">if</span> <span class="n">error</span> <span class="k">else</span> <span class="s1">&#39;info&#39;</span><span class="p">))</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
|
||
<span class="n">sync</span><span class="p">()</span>
|
||
</code></pre></div>
|
||
|
||
<p>This is probably perfectible, but that does the&nbsp;job.</p>
|
||
<p>Last step is to tell you machine to run that frequently. That&#8217;s what
|
||
crontab is made for, so let&#8217;s <code>crontab -e</code>:</p>
|
||
<div class="highlight"><pre><span></span><code> $ <span class="gs">* *</span>/3 <span class="gs">* *</span> * . ~/.Xdbus; /usr/bin/python /home/alexis/dev/python/unison-syncer/sync.py
|
||
</code></pre></div>
|
||
|
||
<p>The \~/.Xdbus allows cron to communicate with your X11 session. Here is
|
||
its&nbsp;content.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="ch">#!/bin/bash</span>
|
||
|
||
<span class="c1"># Get the pid of nautilus</span>
|
||
<span class="nv">nautilus_pid</span><span class="o">=</span><span class="k">$(</span>pgrep<span class="w"> </span>-u<span class="w"> </span><span class="nv">$LOGNAME</span><span class="w"> </span>-n<span class="w"> </span>nautilus<span class="k">)</span>
|
||
|
||
<span class="c1"># If nautilus isn&#39;t running, just exit silently</span>
|
||
<span class="k">if</span><span class="w"> </span><span class="o">[</span><span class="w"> </span>-z<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$nautilus_pid</span><span class="s2">&quot;</span><span class="w"> </span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="k">then</span>
|
||
<span class="nb">exit</span><span class="w"> </span><span class="m">0</span>
|
||
<span class="k">fi</span>
|
||
|
||
<span class="c1"># Grab the DBUS_SESSION_BUS_ADDRESS variable from nautilus&#39;s environment</span>
|
||
<span class="nb">eval</span><span class="w"> </span><span class="k">$(</span>tr<span class="w"> </span><span class="s1">&#39;\0&#39;</span><span class="w"> </span><span class="s1">&#39;\n&#39;</span><span class="w"> </span>&lt;<span class="w"> </span>/proc/<span class="nv">$nautilus_pid</span>/environ<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span><span class="s1">&#39;^DBUS_SESSION_BUS_ADDRESS=&#39;</span><span class="k">)</span>
|
||
|
||
<span class="c1"># Check that we actually found it</span>
|
||
<span class="k">if</span><span class="w"> </span><span class="o">[</span><span class="w"> </span>-z<span class="w"> </span><span class="s2">&quot;</span><span class="nv">$DBUS_SESSION_BUS_ADDRESS</span><span class="s2">&quot;</span><span class="w"> </span><span class="o">]</span><span class="p">;</span><span class="w"> </span><span class="k">then</span>
|
||
<span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;Failed to find bus address&quot;</span><span class="w"> </span>&gt;<span class="p">&amp;</span><span class="m">2</span>
|
||
<span class="nb">exit</span><span class="w"> </span><span class="m">1</span>
|
||
<span class="k">fi</span>
|
||
|
||
<span class="c1"># export it so that child processes will inherit it</span>
|
||
<span class="nb">export</span><span class="w"> </span>DBUS_SESSION_BUS_ADDRESS
|
||
</code></pre></div>
|
||
|
||
<p>And it comes from
|
||
<a href="http://ubuntuforums.org/showthread.php?p=10148738#post10148738">here</a>.</p>
|
||
<p>A sync takes about 20s + the upload time on my machine, which stay
|
||
acceptable for all of my&nbsp;developments.</p></content><category term="code"></category></entry><entry><title>Wrap up of the distutils2 paris’ sprint</title><link href="https://blog.notmyidea.org/wrap-up-of-the-distutils2-paris-sprint.html" rel="alternate"></link><published>2011-02-08T00:00:00+01:00</published><updated>2011-02-08T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-02-08:/wrap-up-of-the-distutils2-paris-sprint.html</id><summary type="html">
|
||
<p>Finally, thanks to a bunch of people that helped me to pay my train and
|
||
bus tickets, I&#8217;ve made it to paris for the distutils2&nbsp;sprint.</p>
|
||
<p>They have been a bit more than 10 people to come during the sprint, and
|
||
it was very productive. Here&#8217;s a taste …</p></summary><content type="html">
|
||
<p>Finally, thanks to a bunch of people that helped me to pay my train and
|
||
bus tickets, I&#8217;ve made it to paris for the distutils2&nbsp;sprint.</p>
|
||
<p>They have been a bit more than 10 people to come during the sprint, and
|
||
it was very productive. Here&#8217;s a taste of what we&#8217;ve been working&nbsp;on:</p>
|
||
<ul>
|
||
<li>the datafiles, a way to specify and to handle the installation of
|
||
files which are not python-related (pictures, manpages and so&nbsp;on).</li>
|
||
<li>mkgcfg, a tool to help you to create a setup.cfg in minutes (and
|
||
with funny&nbsp;examples)</li>
|
||
<li>converters from setup.py scripts. We do now have a piece of code
|
||
which reads your current setup.py file and fill in some fields in
|
||
the setup.cfg for&nbsp;you.</li>
|
||
<li>a compatibility layer for distutils1, so it can read the setup.cfg
|
||
you will wrote for distutils2&nbsp;:-)</li>
|
||
<li>the uninstaller, so it&#8217;s now possible to uninstall what have been
|
||
installed by distutils2 (see <span class="caps">PEP</span>&nbsp;376)</li>
|
||
<li>the installer, and the setuptools compatibility layer, which will
|
||
allow you to rely on setuptools&#8217; based distributions (and there are
|
||
plenty of&nbsp;them!)</li>
|
||
<li>The compilers, so they are more flexible than they were. Since
|
||
that&#8217;s an obscure part of the code for distutils2 commiters (it
|
||
comes directly from the distutils1 ages), having some guys who
|
||
understood the problematics here was a&nbsp;must.</li>
|
||
</ul>
|
||
<p>Some people have also tried to port their packaging from distutils1 to
|
||
distutils2. They have spotted a number of bugs and made some
|
||
improvements to the code, to make it more friendly to&nbsp;use.</p>
|
||
<p>I&#8217;m really pleased to see how newcomers went trough the code, and
|
||
started hacking so fast. I must say it wasn&#8217;t the case when we started
|
||
to work on distutils1 so that&#8217;s a very good point: people now can hack
|
||
the code quicker than they could&nbsp;before.</p>
|
||
<p>Some of the features here are not <em>completely</em> finished yet, but are on
|
||
the tubes, and will be ready for a release (hopefully) at the end of the&nbsp;week.</p>
|
||
<p>Big thanks to logilab for hosting (and sponsoring my train ticket) and
|
||
providing us food, and to bearstech for providing some money for
|
||
breakfast and&nbsp;bears^Wbeers.</p>
|
||
<p>Again, a big thanks to all the people who gave me money to pay the
|
||
transport, I really wasn&#8217;t expecting such thing to happen&nbsp;:-)</p></content><category term="code"></category></entry><entry><title>PyPI on CouchDB</title><link href="https://blog.notmyidea.org/pypi-on-couchdb.html" rel="alternate"></link><published>2011-01-20T00:00:00+01:00</published><updated>2011-01-20T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-01-20:/pypi-on-couchdb.html</id><summary type="html">
|
||
<p>By now, there are two ways to retrieve data from PyPI (the Python
|
||
Package Index). You can both rely on xml/rpc or on the &#8220;simple&#8221; <span class="caps">API</span>. The
|
||
simple <span class="caps">API</span> is not so simple to use as the name suggest, and have several
|
||
existing&nbsp;drawbacks.</p>
|
||
<p>Basically, if you want to …</p></summary><content type="html">
|
||
<p>By now, there are two ways to retrieve data from PyPI (the Python
|
||
Package Index). You can both rely on xml/rpc or on the &#8220;simple&#8221; <span class="caps">API</span>. The
|
||
simple <span class="caps">API</span> is not so simple to use as the name suggest, and have several
|
||
existing&nbsp;drawbacks.</p>
|
||
<p>Basically, if you want to use informations coming from the simple <span class="caps">API</span>,
|
||
you will have to parse web pages manually, to extract informations using
|
||
some black vodoo magic. Badly, magic have a price, and it&#8217;s sometimes
|
||
impossible to get exactly the informations you want to get from this
|
||
index. That&#8217;s the technique currently being used by distutils2,
|
||
setuptools and&nbsp;pip.</p>
|
||
<p>On the other side, while <span class="caps">XML</span>/<span class="caps">RPC</span> is working fine, it&#8217;s requiring extra
|
||
work to the python servers each time you request something, which can
|
||
lead to some outages from time to time. Also, it&#8217;s important to point
|
||
out that, even if PyPI have a mirroring infrastructure, it&#8217;s only for
|
||
the so-called <em>simple</em> <span class="caps">API</span>, and not for the <span class="caps">XML</span>/<span class="caps">RPC</span>.</p>
|
||
<h2 id="couchdb">CouchDB</h2>
|
||
<p>Here comes CouchDB. CouchDB is a document oriented database, that knows
|
||
how to speak <span class="caps">REST</span> and <span class="caps">JSON</span>. It&#8217;s easy to use, and provides out of the
|
||
box a replication&nbsp;mechanism.</p>
|
||
<h2 id="so-what">So, what&nbsp;?</h2>
|
||
<p>Hmm, I&#8217;m sure you got it. I&#8217;ve wrote a piece of software to link
|
||
informations from PyPI to a CouchDB instance. Then you can replicate all
|
||
the PyPI index with only one <span class="caps">HTTP</span> request on the CouchDB server. You can
|
||
also access the informations from the index directly using a <span class="caps">REST</span> <span class="caps">API</span>,
|
||
speaking json.&nbsp;Handy.</p>
|
||
<p>So PyPIonCouch is using the PyPI <span class="caps">XML</span>/<span class="caps">RPC</span> <span class="caps">API</span> to get data from PyPI, and
|
||
generate records in the CouchDB&nbsp;instance.</p>
|
||
<p>The final goal is to avoid to rely on this &#8220;simple&#8221; <span class="caps">API</span>, and rely on a
|
||
<span class="caps">REST</span> insterface instead. I have set up a couchdb server on my server,
|
||
which is available at
|
||
<a href="http://couchdb.notmyidea.org/_utils/database.html?pypi">http://couchdb.notmyidea.org/_utils/database.html?pypi</a>.</p>
|
||
<p>There is not a lot to see there for now, but I&#8217;ve done the first import
|
||
from PyPI yesterday and all went fine: it&#8217;s possible to access the
|
||
metadata of all PyPI projects via a <span class="caps">REST</span> interface. Next step is to
|
||
write a client for this <span class="caps">REST</span> interface in&nbsp;distutils2.</p>
|
||
<h2 id="example">Example</h2>
|
||
<p>For now, you can use pypioncouch via the command line, or via the python
|
||
<span class="caps">API</span>.</p>
|
||
<h3 id="using-the-command-line">Using the command&nbsp;line</h3>
|
||
<p>You can do something like that for a full import. This <strong>will</strong> take
|
||
long, because it&#8217;s fetching all the projects at pypi and importing their&nbsp;metadata:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="err">$</span> <span class="n">pypioncouch</span> <span class="o">--</span><span class="n">fullimport</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="n">your</span><span class="o">.</span><span class="n">couchdb</span><span class="o">.</span><span class="n">instance</span><span class="o">/</span>
|
||
</code></pre></div>
|
||
|
||
<p>If you already have the data on your couchdb instance, you can just
|
||
update it with the last informations from pypi. <strong>However, I recommend
|
||
to just replicate the principal node, hosted at
|
||
<a href="http://couchdb.notmyidea.org/pypi/">http://couchdb.notmyidea.org/pypi/</a></strong>, to avoid the duplication of&nbsp;nodes:</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pypioncouch<span class="w"> </span>--update<span class="w"> </span>http://your.couchdb.instance/
|
||
</code></pre></div>
|
||
|
||
<p>The principal node is updated once a day by now, I&#8217;ll try to see if it&#8217;s
|
||
enough, and ajust with the&nbsp;time.</p>
|
||
<h3 id="using-the-python-api">Using the python <span class="caps">API</span></h3>
|
||
<p>You can also use the python <span class="caps">API</span> to interact with&nbsp;pypioncouch:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">pypioncouch</span> <span class="kn">import</span> <span class="n">XmlRpcImporter</span><span class="p">,</span> <span class="n">import_all</span><span class="p">,</span> <span class="n">update</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">full_import</span><span class="p">()</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">update</span><span class="p">()</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="whats-next">What&#8217;s next&nbsp;?</h2>
|
||
<p>I want to make a couchapp, in order to navigate PyPI easily. Here are
|
||
some of the features I want to&nbsp;propose:</p>
|
||
<ul>
|
||
<li>List all the available&nbsp;projects</li>
|
||
<li>List all the projects, filtered by&nbsp;specifiers</li>
|
||
<li>List all the projects by&nbsp;author/maintainer</li>
|
||
<li>List all the projects by&nbsp;keywords</li>
|
||
<li>Page for each&nbsp;project.</li>
|
||
<li>Provide a PyPI &#8220;Simple&#8221; <span class="caps">API</span> equivalent, even if I want to replace
|
||
it, I do think it will be really easy to setup mirrors that way,
|
||
with the out of the box couchdb&nbsp;replication</li>
|
||
</ul>
|
||
<p>I also still need to polish the import mechanism, so I can directly
|
||
store in&nbsp;couchdb:</p>
|
||
<ul>
|
||
<li>The <span class="caps">OPML</span> files for each&nbsp;project</li>
|
||
<li>The upload_time as couchdb friendly format (list of&nbsp;int)</li>
|
||
<li>The tags as lists (currently it&#8217;s only a string separated by&nbsp;spaces</li>
|
||
</ul>
|
||
<p>The work I&#8217;ve done by now is available on
|
||
<a href="https://bitbucket.org/ametaireau/pypioncouch/">https://bitbucket.org/ametaireau/pypioncouch/</a>. Keep in mind that it&#8217;s
|
||
still a work in progress, and everything can break at any time. However,
|
||
any feedback will be appreciated&nbsp;!</p></content><category term="code"></category></entry><entry><title>Help me to go to the distutils2 paris’ sprint</title><link href="https://blog.notmyidea.org/help-me-to-go-to-the-distutils2-paris-sprint.html" rel="alternate"></link><published>2011-01-15T00:00:00+01:00</published><updated>2011-01-15T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2011-01-15:/help-me-to-go-to-the-distutils2-paris-sprint.html</id><summary type="html">
|
||
<p><strong>Edit: Thanks to logilab and some amazing people, I can make it to
|
||
paris for the sprint. Many thanks to them for the&nbsp;support!</strong></p>
|
||
<p>There will be a distutils2 sprint from the 27th to the 30th of january,
|
||
thanks to logilab which will host the&nbsp;event.</p>
|
||
<p>You can find more …</p></summary><content type="html">
|
||
<p><strong>Edit: Thanks to logilab and some amazing people, I can make it to
|
||
paris for the sprint. Many thanks to them for the&nbsp;support!</strong></p>
|
||
<p>There will be a distutils2 sprint from the 27th to the 30th of january,
|
||
thanks to logilab which will host the&nbsp;event.</p>
|
||
<p>You can find more informations about the sprint on the wiki page of the
|
||
event (<a href="http://wiki.python.org/moin/Distutils/SprintParis">http://wiki.python.org/moin/Distutils/SprintParis</a>).</p>
|
||
<p>I really want to go there but I&#8217;m unfortunately blocked in <span class="caps">UK</span> for money
|
||
reasons. The cheapest two ways I&#8217;ve found is about £80, which I can&#8217;t
|
||
afford. Following some advices on #distutils, I&#8217;ve set up a ChipIn
|
||
account for that, so if some people want to help me making it to go
|
||
there, they can give me some money that&nbsp;way.</p>
|
||
<p>I&#8217;ll probably work on the installer (to support old distutils and
|
||
setuptools distributions) and on the uninstaller (depending on the first
|
||
task). If I can&#8217;t make it to paris, I&#8217;ll hang around on <span class="caps">IRC</span> to give some
|
||
help while&nbsp;needed.</p>
|
||
<p>If you want to contribute some money to help me go there, feel free to
|
||
use this chipin page:
|
||
<a href="http://ametaireau.chipin.com/distutils2-sprint-in-paris">http://ametaireau.chipin.com/distutils2-sprint-in-paris</a></p>
|
||
<p>Thanks for your support&nbsp;!</p></content><category term="code"></category></entry><entry><title>Fork you! or how the social coding can help you</title><link href="https://blog.notmyidea.org/fork-you-or-how-the-social-coding-can-help-you.html" rel="alternate"></link><published>2010-11-05T00:00:00+01:00</published><updated>2010-11-05T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-11-05:/fork-you-or-how-the-social-coding-can-help-you.html</id><summary type="html">
|
||
<p>With <a href="http://github.com">github</a> and
|
||
<a href="http://www.bitbucket.org">bitbucket</a> coming around, a lot of new usages
|
||
appears for the developpers: it&#8217;s now easy to get feedback on your
|
||
code/modifications, and to get help from others by, for instance,
|
||
forking&nbsp;repositories.</p>
|
||
<p>Eeach time I see people helping others, I&#8217;m amazed by how we …</p></summary><content type="html">
|
||
<p>With <a href="http://github.com">github</a> and
|
||
<a href="http://www.bitbucket.org">bitbucket</a> coming around, a lot of new usages
|
||
appears for the developpers: it&#8217;s now easy to get feedback on your
|
||
code/modifications, and to get help from others by, for instance,
|
||
forking&nbsp;repositories.</p>
|
||
<p>Eeach time I see people helping others, I&#8217;m amazed by how we like to
|
||
share our&nbsp;knowledge.</p>
|
||
<p>I say github, because it seems to be the more mainstream, but I think
|
||
it&#8217;s something strongly related to the
|
||
<a href="http://en.wikipedia.org/wiki/Distributed_revision_control"><span class="caps">DVCS</span></a>
|
||
principles: the &#8220;only&#8221; thing github have made is to turn that into a
|
||
social network, and to reveal the awesomeness of the DVCSes to the&nbsp;masses.</p>
|
||
<p>What is really interesting is to see how this platform is addictive:
|
||
it&#8217;s automatically updating a webpages with the more accurate
|
||
informations about the projects you&#8217;re involved in, and add a bit of
|
||
magic to that using webhooks, allowing you to update your website each
|
||
time you push to you repository, for&nbsp;instance.</p>
|
||
<p>Quite nothing, indeed, but, I don&#8217;t know why, I find this&nbsp;fascinating.</p>
|
||
<p>I haven&#8217;t had the privilege to see my projects forked from github by
|
||
strangers, but I&#8217;ve forked others repository to give an hand some times,
|
||
when I wanted to, and the main reason is &#8220;because it&#8217;s <strong>fun</strong>&#8221; to do&nbsp;so.</p>
|
||
<p>Yeah, you&#8217;re probably right, you have to be a nerd to find fun to fork
|
||
others. The good point is that geeks are a kind of nerds, and some geeks
|
||
are coders&nbsp;:)</p>
|
||
<h2 id="new-ways-to-contribute">New ways to&nbsp;contribute</h2>
|
||
<p>In addition, it seems that he community, or the communities, are there,
|
||
on those new social networks for coders. It&#8217;s really handy to drop an
|
||
eye on interesting projects, to report bugs, propose new features, and
|
||
check what new projects this or this person have&nbsp;made.</p>
|
||
<p>Well, &#8220;it&#8217;s not new&#8221;, you may think. That&#8217;s true, because it&#8217;s been a
|
||
while that <span class="caps">SVN</span> was there and even <span class="caps">CVS</span> before that. But, it was a bit
|
||
messy to &#8220;fork&#8221; a project, isn&#8217;t it ? And I&#8217;m not talking about all the
|
||
hell <span class="caps">SVN</span> involved with it (who have not had issues with those messy .svn
|
||
folders raises an hand&nbsp;!).</p>
|
||
<p>It have not been so easy to share code and thoughts about code, to
|
||
propose changes on existing code, than now. You think it&#8217;s better to
|
||
implement this or that in a different way ? Clone it (fork it), make
|
||
your changes and publish them, and then ask projects owners about it.
|
||
For sure you&#8217;ll have&nbsp;answers.</p>
|
||
<p>Even if they don&#8217;t want it, you can easily keep your changes, and keep
|
||
getting their&nbsp;updates!</p>
|
||
<p>Also, lot of <em>fashionables</em> projects tend to move on <span class="caps">DVCS</span>. Personally,
|
||
if I know I can fork on a <span class="caps">DVCS</span> instead of from a &#8220;simple&#8221; <span class="caps">VCS</span>, I&#8217;ll
|
||
probably be quicker to fork/clone, and to publish changes on my own
|
||
copy, than if I had to do so on the upstream repository (and I&#8217;ll likely
|
||
dont have the rights to push to it), because I will not be afraid to
|
||
break&nbsp;things.</p>
|
||
<p>DVCSes makes the contribution&nbsp;easier.</p>
|
||
<h2 id="release-early-release-often">Release early, release&nbsp;often</h2>
|
||
<p>Maybe have you read <a href="http://www.catb.org/~esr/writings/cathedral-bazaar/">The cathedral and the
|
||
bazaar</a>, by Eric
|
||
Steven Raymond ? (If not, consider doing so, it&#8217;s a really interesting&nbsp;reading)</p>
|
||
<p>Among a lot of others interesting things, one hint he gives is <em>release
|
||
early, release often</em>.</p>
|
||
<p>I understand it as: if you want to get contributors, release your code
|
||
early, even if it&#8217;s not perfect, and don&#8217;t be afraid to publish your
|
||
changes each time it&#8217;s&nbsp;needed.</p>
|
||
<p>Without notifying it, that&#8217;s basically what I was doing for my own
|
||
projects. I guess that&#8217;s because Social coding platforms encourages
|
||
those practices, partially cause of the possible impact publishing each
|
||
of your changes can have on your final&nbsp;solution.</p>
|
||
<p>If you have considered publishing your projects, code snippets, or
|
||
whatever (code related) but did not done it, considering them not yet
|
||
ready, maybe should you think about it twice: you can get feedback and
|
||
probably start some interesting discussions about it, if you write code
|
||
that&#8217;s readable, of&nbsp;course!</p>
|
||
<h2 id="a-step-further-for-open-source-softwares">A step further for open source&nbsp;softwares</h2>
|
||
<p>Well, DVCSes are a honking great idea, and they&#8217;re starting to be really
|
||
powerful when applied to free softwares. I mean: if you can&#8217;t see a
|
||
project, it will be hard to contribute to it. And, I don&#8217;t think anyone
|
||
wants to contribute to something closed/proprietary, <em>just for fun</em>. Or
|
||
maybe am I missing&nbsp;something.</p>
|
||
<p>Maybe it&#8217;s a kind of revolution, about free and open source softwares
|
||
(<a href="http://en.wikipedia.org/wiki/Free_and_open_source_software"><span class="caps">FOSS</span></a>),
|
||
that is going on. I really like to know I have my word to say about the
|
||
changes in the tools I use, and to know that I can make them&nbsp;evolve.</p>
|
||
<p>Let&#8217;s take an example. Imagine I&#8217;m using a web framework on daily basis,
|
||
as a part of my job as a web developer. I do like using an open source
|
||
software because I know how it&#8217;s working, and because I know that I can
|
||
interact with the authors of the framework while they&#8217;re doing the
|
||
changes on&nbsp;it.</p>
|
||
<p>That&#8217;s communication, nothing more, and of course I can do that with an
|
||
internal proprietary solution, but it will cost me <strong>a lot</strong> more time,
|
||
for a dead-simple reason: a company is not as big and powerful as a
|
||
community can be: it will cost time to work on this framework, resources
|
||
to maintain it, fix bugs&nbsp;etc.</p>
|
||
<p>Well, I&#8217;m starting advocating here about Free and Open Source Softwares
|
||
use on companies, what is a bit beyond the scope of this article, so
|
||
let&#8217;s back to our DVCSes and new social related&nbsp;tools.</p>
|
||
<p>If I find a bug in this framework, while working, I have the possibility
|
||
to go and talk with the creators of the framework, to open a ticket, and
|
||
even to make a fix for it, because I&#8217;ve access to the source code. If I
|
||
want to create a new feature, I just have to fork it, hack it, and then
|
||
publish my code to have feedback of the&nbsp;community.</p>
|
||
<p>My fix/work will benefit to all the people (and maybe others companies)
|
||
working with this framework, and it&#8217;s a way to prove the community that
|
||
my company is enough skilled to make code-fixes to the framework, so
|
||
that&#8217;s all good&nbsp;!</p>
|
||
<h2 id="whats-next">What&#8217;s next&nbsp;?</h2>
|
||
<p>I hope those social coding platforms are only the begining of a new
|
||
area. I hope they will make people realize what the power of the
|
||
community is, and how easily they can becomes part of&nbsp;it.</p>
|
||
<p>If you&#8217;re not using them right now, maybe you should do so: have a look
|
||
on how the programs you&#8217;re using are made, consider publishing your
|
||
experimentations, and share them with others, you will see, it&#8217;s kind of
|
||
addictive&nbsp;!</p></content><category term="journal"></category></entry><entry><title>How to reboot your bebox using the CLI</title><link href="https://blog.notmyidea.org/how-to-reboot-your-bebox-using-the-cli.html" rel="alternate"></link><published>2010-10-21T00:00:00+02:00</published><updated>2010-10-21T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-10-21:/how-to-reboot-your-bebox-using-the-cli.html</id><summary type="html">
|
||
<p>I&#8217;ve an internet connection which, for some obscure reasons, tend to be
|
||
very slow from time to time. After rebooting the box (yes, that&#8217;s a hard
|
||
solution), all the things seems to go fine&nbsp;again.</p>
|
||
<h2 id="edit-using-grep"><span class="caps">EDIT</span> : Using&nbsp;grep</h2>
|
||
<p>After a bit of reflexion, that&#8217;s also really easy …</p></summary><content type="html">
|
||
<p>I&#8217;ve an internet connection which, for some obscure reasons, tend to be
|
||
very slow from time to time. After rebooting the box (yes, that&#8217;s a hard
|
||
solution), all the things seems to go fine&nbsp;again.</p>
|
||
<h2 id="edit-using-grep"><span class="caps">EDIT</span> : Using&nbsp;grep</h2>
|
||
<p>After a bit of reflexion, that&#8217;s also really easy to do using directly
|
||
the command line tools curl, grep and tail (but really harder to&nbsp;read).</p>
|
||
<div class="highlight"><pre><span></span><code>curl<span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span>-u<span class="w"> </span>joel:joel<span class="w"> </span>http://bebox.config/cgi/b/info/restart/<span class="se">\?</span>be<span class="se">\=</span><span class="m">0</span><span class="se">\&amp;</span>l0<span class="se">\=</span><span class="m">1</span><span class="se">\&amp;</span>l1<span class="se">\=</span><span class="m">0</span><span class="se">\&amp;</span>tid<span class="se">\=</span>RESTART<span class="w"> </span>-d<span class="w"> </span><span class="s2">&quot;0=17&amp;2=`curl -u joel:joel http://bebox.config/cgi/b/info/restart/\?be\=0\&amp;l0\=1\&amp;l1\=0\&amp;tid\=RESTART | grep -o &quot;</span><span class="nv">name</span><span class="o">=</span><span class="s1">&#39;2&#39;</span><span class="w"> </span><span class="nv">value</span><span class="o">=</span><span class="err">&#39;</span><span class="o">[</span><span class="m">0</span>-9<span class="o">]</span><span class="se">\+</span><span class="s2">&quot; | grep -o &quot;</span><span class="o">[</span><span class="m">0</span>-9<span class="o">]</span><span class="se">\+</span><span class="s2">&quot; | tail -n 1`&amp;1&quot;</span>
|
||
</code></pre></div>
|
||
|
||
<h2 id="the-python-version">The Python&nbsp;version</h2>
|
||
<p>Well, that&#8217;s not the optimal solution, that&#8217;s a bit &#8220;gruik&#8221;, but it&nbsp;works.</p>
|
||
<div class="highlight"><pre><span></span><code><span class="kn">import</span> <span class="nn">urllib2</span>
|
||
<span class="kn">import</span> <span class="nn">urlparse</span>
|
||
<span class="kn">import</span> <span class="nn">re</span>
|
||
<span class="kn">import</span> <span class="nn">argparse</span>
|
||
|
||
<span class="n">REBOOT_URL</span> <span class="o">=</span> <span class="s1">&#39;/b/info/restart/?be=0&amp;l0=1&amp;l1=0&amp;tid=RESTART&#39;</span>
|
||
<span class="n">BOX_URL</span> <span class="o">=</span> <span class="s1">&#39;http://bebox.config/cgi&#39;</span>
|
||
|
||
<span class="k">def</span> <span class="nf">open_url</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
|
||
<span class="n">passman</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">HTTPPasswordMgrWithDefaultRealm</span><span class="p">()</span>
|
||
<span class="n">passman</span><span class="o">.</span><span class="n">add_password</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
|
||
<span class="n">authhandler</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">HTTPBasicAuthHandler</span><span class="p">(</span><span class="n">passman</span><span class="p">)</span>
|
||
|
||
<span class="n">opener</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">build_opener</span><span class="p">(</span><span class="n">authhandler</span><span class="p">)</span>
|
||
|
||
<span class="n">urllib2</span><span class="o">.</span><span class="n">install_opener</span><span class="p">(</span><span class="n">opener</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||
|
||
<span class="k">def</span> <span class="nf">reboot</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
|
||
<span class="n">data</span> <span class="o">=</span> <span class="n">open_url</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
|
||
<span class="n">token</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s2">&quot;name\=</span><span class="se">\\</span><span class="s2">&#39;2</span><span class="se">\\</span><span class="s2">&#39; value=</span><span class="se">\\</span><span class="s2">&#39;([0-9]+)</span><span class="se">\\</span><span class="s2">&#39;&quot;</span><span class="p">,</span> <span class="n">data</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">urllib2</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="s1">&#39;0=17&amp;2=</span><span class="si">%s</span><span class="s1">&amp;1&#39;</span> <span class="o">%</span> <span class="n">token</span><span class="p">))</span>
|
||
|
||
<span class="k">if</span> <span class="vm">__file__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
|
||
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">&quot;&quot;&quot;Reboot your bebox !&quot;&quot;&quot;</span><span class="p">)</span>
|
||
|
||
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="n">dest</span><span class="o">=</span><span class="s1">&#39;user&#39;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;username&#39;</span><span class="p">)</span>
|
||
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="n">dest</span><span class="o">=</span><span class="s1">&#39;password&#39;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;password&#39;</span><span class="p">)</span>
|
||
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="n">boxurl</span><span class="o">=</span><span class="s1">&#39;boxurl&#39;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">BOX_URL</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s1">&#39;Base box url. Default is </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">BOX_URL</span><span class="p">)</span>
|
||
|
||
<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
|
||
<span class="n">url</span> <span class="o">=</span> <span class="n">urlparse</span><span class="o">.</span><span class="n">urljoin</span><span class="p">(</span><span class="n">args</span><span class="o">.</span><span class="n">boxurl</span><span class="p">,</span> <span class="n">REBOOT_URL</span><span class="p">)</span>
|
||
<span class="n">reboot</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">username</span><span class="p">,</span> <span class="n">args</span><span class="o">.</span><span class="n">password</span><span class="p">)</span>
|
||
</code></pre></div></content><category term="code"></category></entry><entry><title>Dynamically change your gnome desktop wallpaper</title><link href="https://blog.notmyidea.org/dynamically-change-your-gnome-desktop-wallpaper.html" rel="alternate"></link><published>2010-10-11T00:00:00+02:00</published><updated>2010-10-11T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-10-11:/dynamically-change-your-gnome-desktop-wallpaper.html</id><summary type="html">
|
||
<p>In gnome, you can can use a <span class="caps">XML</span> file to have a dynamic wallpaper. It&#8217;s
|
||
not so easy, and you can&#8217;t just tell: use the pictures in this folder to
|
||
do&nbsp;so.</p>
|
||
<p>You can have a look to the git repository if you want:
|
||
<a href="http://github.com/ametaireau/gnome-background-generator">http://github.com/ametaireau …</a></p></summary><content type="html">
|
||
<p>In gnome, you can can use a <span class="caps">XML</span> file to have a dynamic wallpaper. It&#8217;s
|
||
not so easy, and you can&#8217;t just tell: use the pictures in this folder to
|
||
do&nbsp;so.</p>
|
||
<p>You can have a look to the git repository if you want:
|
||
<a href="http://github.com/ametaireau/gnome-background-generator">http://github.com/ametaireau/gnome-background-generator</a></p>
|
||
<p>Some time ago, I&#8217;ve made a little python script to ease that, and you
|
||
can now use it too. It&#8217;s named &#8220;gnome-background-generator&#8221;, and you can
|
||
install it via pip for&nbsp;instance.</p>
|
||
<div class="highlight"><pre><span></span><code>shell
|
||
$ pip install gnome-background-generator
|
||
</code></pre></div>
|
||
|
||
<p>Then, you have just to use it this&nbsp;way:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">shell</span>
|
||
<span class="n">$ gnome-background-generator -p ~/Images/walls -s</span>
|
||
<span class="n">/home/alexis/Images/walls/dynamic-wallpaper.xml generated</span>
|
||
</code></pre></div>
|
||
|
||
<p>Here is a extract of the&nbsp;`&#8212;help`:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="n">shell</span>
|
||
<span class="o">$</span><span class="w"> </span><span class="n">gnome</span><span class="o">-</span><span class="n">background</span><span class="o">-</span><span class="n">generator</span><span class="w"> </span><span class="o">--</span><span class="n">help</span>
|
||
<span class="n">usage</span><span class="p">:</span><span class="w"> </span><span class="n">gnome</span><span class="o">-</span><span class="n">background</span><span class="o">-</span><span class="n">generator</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">h</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">p</span><span class="w"> </span><span class="n">PATH</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">o</span><span class="w"> </span><span class="n">OUTPUT</span><span class="p">]</span>
|
||
<span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">t</span><span class="w"> </span><span class="n">TRANSITION_TIME</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">d</span><span class="w"> </span><span class="n">DISPLAY_TIME</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">s</span><span class="p">]</span>
|
||
<span class="w"> </span><span class="p">[</span><span class="o">-</span><span class="n">b</span><span class="p">]</span>
|
||
|
||
<span class="n">A</span><span class="w"> </span><span class="n">simple</span><span class="w"> </span><span class="n">command</span><span class="w"> </span><span class="n">line</span><span class="w"> </span><span class="k">tool</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">generate</span><span class="w"> </span><span class="n">an</span><span class="w"> </span><span class="n">XML</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">gnome</span>
|
||
<span class="n">wallpapers</span><span class="p">,</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">have</span><span class="w"> </span><span class="n">dynamic</span><span class="w"> </span><span class="n">walls</span>
|
||
|
||
<span class="n">optional</span><span class="w"> </span><span class="n">arguments</span><span class="p">:</span>
|
||
<span class="w"> </span><span class="o">-</span><span class="n">h</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">help</span><span class="w"> </span><span class="n">show</span><span class="w"> </span><span class="n">this</span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="n">message</span><span class="w"> </span><span class="ow">and</span><span class="w"> </span><span class="n">exit</span>
|
||
<span class="w"> </span><span class="o">-</span><span class="n">p</span><span class="w"> </span><span class="n">PATH</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">path</span><span class="w"> </span><span class="n">PATH</span><span class="w"> </span><span class="n">Path</span><span class="w"> </span><span class="n">to</span><span class="w"> </span><span class="n">look</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">pictures</span><span class="o">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">output</span><span class="w"> </span><span class="k">is</span>
|
||
<span class="w"> </span><span class="n">specified</span><span class="p">,</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">used</span><span class="w"> </span><span class="n">too</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">outputing</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">dynamic</span><span class="o">-</span>
|
||
<span class="w"> </span><span class="n">wallpaper</span><span class="o">.</span><span class="n">xml</span><span class="w"> </span><span class="n">file</span><span class="o">.</span><span class="w"> </span><span class="n">Default</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">current</span>
|
||
<span class="w"> </span><span class="n">directory</span><span class="w"> </span><span class="p">(</span><span class="o">.</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="o">-</span><span class="n">o</span><span class="w"> </span><span class="n">OUTPUT</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">output</span><span class="w"> </span><span class="n">OUTPUT</span>
|
||
<span class="w"> </span><span class="n">Output</span><span class="w"> </span><span class="n">filename</span><span class="o">.</span><span class="w"> </span><span class="n">If</span><span class="w"> </span><span class="n">no</span><span class="w"> </span><span class="n">filename</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">specified</span><span class="p">,</span><span class="w"> </span><span class="n">a</span>
|
||
<span class="w"> </span><span class="n">dynamic</span><span class="o">-</span><span class="n">wallpaper</span><span class="o">.</span><span class="n">xml</span><span class="w"> </span><span class="n">file</span><span class="w"> </span><span class="n">will</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">generated</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span>
|
||
<span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="n">containing</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">pictures</span><span class="o">.</span><span class="w"> </span><span class="n">You</span><span class="w"> </span><span class="n">can</span><span class="w"> </span><span class="n">also</span><span class="w"> </span><span class="n">use</span><span class="w"> </span><span class="s2">&quot;-&quot;</span><span class="w"> </span><span class="n">to</span>
|
||
<span class="w"> </span><span class="n">display</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">xml</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="n">the</span><span class="w"> </span><span class="n">stdout</span><span class="o">.</span>
|
||
<span class="w"> </span><span class="o">-</span><span class="n">t</span><span class="w"> </span><span class="n">TRANSITION_TIME</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">transition</span><span class="o">-</span><span class="n">time</span><span class="w"> </span><span class="n">TRANSITION_TIME</span>
|
||
<span class="w"> </span><span class="n">Time</span><span class="w"> </span><span class="p">(</span><span class="ow">in</span><span class="w"> </span><span class="n">seconds</span><span class="p">)</span><span class="w"> </span><span class="n">transitions</span><span class="w"> </span><span class="n">must</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="p">(</span><span class="n">default</span><span class="w"> </span><span class="n">value</span>
|
||
<span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">seconds</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="o">-</span><span class="n">d</span><span class="w"> </span><span class="n">DISPLAY_TIME</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">display</span><span class="o">-</span><span class="n">time</span><span class="w"> </span><span class="n">DISPLAY_TIME</span>
|
||
<span class="w"> </span><span class="n">Time</span><span class="w"> </span><span class="p">(</span><span class="ow">in</span><span class="w"> </span><span class="n">seconds</span><span class="p">)</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">picture</span><span class="w"> </span><span class="n">must</span><span class="w"> </span><span class="n">be</span><span class="w"> </span><span class="n">displayed</span><span class="o">.</span><span class="w"> </span><span class="n">Default</span>
|
||
<span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="mi">900</span><span class="w"> </span><span class="p">(</span><span class="mi">15</span><span class="n">mn</span><span class="p">)</span>
|
||
<span class="w"> </span><span class="o">-</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">set</span><span class="o">-</span><span class="n">background</span><span class="w"> </span><span class="s1">&#39;&#39;&#39;try to set the background using gnome-appearance-</span>
|
||
<span class="s1"> properties</span>
|
||
<span class="s1"> -b, --debug</span>
|
||
</code></pre></div></content><category term="code"></category></entry><entry><title>How to install NGINX + PHP 5.3 on FreeBSD.</title><link href="https://blog.notmyidea.org/how-to-install-nginx-php-53-on-freebsd.html" rel="alternate"></link><published>2010-10-10T00:00:00+02:00</published><updated>2010-10-10T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-10-10:/how-to-install-nginx-php-53-on-freebsd.html</id><summary type="html">
|
||
<ul>
|
||
<li>
|
||
<p>date<br>&nbsp;2010-10-10</p>
|
||
</li>
|
||
<li>
|
||
<p>category<br>&nbsp;tech</p>
|
||
</li>
|
||
</ul>
|
||
<p>I&#8217;ve not managed so far to get completely rid of php, so here&#8217;s a simple
|
||
reminder about how to install php on <span class="caps">NGINX</span>, for FreeBSD. Nothing hard,
|
||
but that&#8217;s worse to have the piece of configuration somewhere&nbsp;!</p>
|
||
<div class="highlight"><pre><span></span><code><span class="err">#</span><span class="w"> </span><span class="nx">update</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">ports</span>
|
||
<span class="err">$</span><span class="w"> </span><span class="nx">portsnap</span><span class="w"> </span><span class="nx">fetch</span><span class="w"> </span><span class="nx">update …</span></code></pre></div></summary><content type="html">
|
||
<ul>
|
||
<li>
|
||
<p>date<br>&nbsp;2010-10-10</p>
|
||
</li>
|
||
<li>
|
||
<p>category<br>&nbsp;tech</p>
|
||
</li>
|
||
</ul>
|
||
<p>I&#8217;ve not managed so far to get completely rid of php, so here&#8217;s a simple
|
||
reminder about how to install php on <span class="caps">NGINX</span>, for FreeBSD. Nothing hard,
|
||
but that&#8217;s worse to have the piece of configuration somewhere&nbsp;!</p>
|
||
<div class="highlight"><pre><span></span><code><span class="err">#</span><span class="w"> </span><span class="nx">update</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">ports</span>
|
||
<span class="err">$</span><span class="w"> </span><span class="nx">portsnap</span><span class="w"> </span><span class="nx">fetch</span><span class="w"> </span><span class="nx">update</span>
|
||
|
||
<span class="err">#</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nx">php5</span><span class="w"> </span><span class="nx">port</span>
|
||
<span class="err">$</span><span class="w"> </span><span class="nx">make</span><span class="w"> </span><span class="nx">config</span><span class="o">-</span><span class="nx">recursive</span><span class="w"> </span><span class="o">-</span><span class="nx">C</span><span class="w"> </span><span class="o">/</span><span class="nx">usr</span><span class="o">/</span><span class="nx">ports</span><span class="o">/</span><span class="nx">lang</span><span class="o">/</span><span class="nx">php5</span><span class="o">-</span><span class="nx">extensions</span>
|
||
<span class="err">$</span><span class="w"> </span><span class="nx">make</span><span class="w"> </span><span class="kn">package</span><span class="o">-</span><span class="nx">recursive</span><span class="w"> </span><span class="o">-</span><span class="nx">C</span><span class="w"> </span><span class="o">/</span><span class="nx">usr</span><span class="o">/</span><span class="nx">ports</span><span class="o">/</span><span class="nx">lang</span><span class="o">/</span><span class="nx">php5</span><span class="o">-</span><span class="nx">extensions</span>
|
||
|
||
<span class="err">#</span><span class="w"> </span><span class="nx">install</span><span class="w"> </span><span class="nx">nginx</span>
|
||
<span class="err">$</span><span class="w"> </span><span class="nx">make</span><span class="w"> </span><span class="nx">config</span><span class="o">-</span><span class="nx">recursive</span><span class="w"> </span><span class="o">-</span><span class="nx">C</span><span class="w"> </span><span class="o">/</span><span class="nx">usr</span><span class="o">/</span><span class="nx">ports</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">nginx</span><span class="o">-</span><span class="nx">devel</span>
|
||
<span class="err">$</span><span class="w"> </span><span class="nx">make</span><span class="w"> </span><span class="kn">package</span><span class="o">-</span><span class="nx">recursive</span><span class="w"> </span><span class="o">-</span><span class="nx">C</span><span class="w"> </span><span class="o">/</span><span class="nx">usr</span><span class="o">/</span><span class="nx">ports</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">nginx</span><span class="o">-</span><span class="nx">devel</span>
|
||
</code></pre></div>
|
||
|
||
<p>Now we have all the dependencies installed, we need to configure a bit
|
||
the&nbsp;server.</p>
|
||
<p>That&#8217;s a simple thing in fact, but it could be good to have something
|
||
that will work without effort over&nbsp;time.</p>
|
||
<p>Here&#8217;s a sample of my&nbsp;configuration:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nt">server</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="err">server_name</span><span class="w"> </span><span class="err">ndd</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="err">set</span><span class="w"> </span><span class="err">$path</span><span class="w"> </span><span class="err">/path/to/your/files</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="err">root</span><span class="w"> </span><span class="err">$path</span><span class="p">;</span>
|
||
|
||
<span class="w"> </span><span class="err">location</span><span class="w"> </span><span class="err">/</span><span class="w"> </span><span class="err">{</span>
|
||
<span class="w"> </span><span class="err">index</span><span class="w"> </span><span class="err">index.php</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="nt">location</span><span class="w"> </span><span class="o">~*</span><span class="w"> </span><span class="o">^.+.(</span><span class="nt">jpg</span><span class="o">|</span><span class="nt">jpeg</span><span class="o">|</span><span class="nt">gif</span><span class="o">|</span><span class="nt">css</span><span class="o">|</span><span class="nt">png</span><span class="o">|</span><span class="nt">js</span><span class="o">|</span><span class="nt">ico</span><span class="o">|</span><span class="nt">xml</span><span class="o">)$</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="err">access_log</span><span class="w"> </span><span class="err">off</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="err">expires</span><span class="w"> </span><span class="err">30d</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="w"> </span><span class="nt">location</span><span class="w"> </span><span class="o">~</span><span class="w"> </span><span class="p">.</span><span class="nc">php</span><span class="o">$</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="err">fastcgi_param</span><span class="w"> </span><span class="err">SCRIPT_FILENAME</span><span class="w"> </span><span class="err">$path$fastcgi_script_name</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="err">fastcgi_pass</span><span class="w"> </span><span class="err">backend</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="err">include</span><span class="w"> </span><span class="err">fastcgi_params</span><span class="p">;</span>
|
||
<span class="w"> </span><span class="p">}</span>
|
||
<span class="err">}</span>
|
||
|
||
<span class="nt">upstream</span><span class="w"> </span><span class="nt">backend</span><span class="w"> </span><span class="p">{</span>
|
||
<span class="w"> </span><span class="err">server</span><span class="w"> </span><span class="err">127.0.0.1:9000</span><span class="p">;</span>
|
||
<span class="p">}</span>
|
||
</code></pre></div>
|
||
|
||
<p>And that&#8217;s it&nbsp;!</p></content><category term="code"></category></entry><entry><title>Pelican, a simple static blog generator in python</title><link href="https://blog.notmyidea.org/pelican-a-simple-static-blog-generator-in-python.html" rel="alternate"></link><published>2010-10-06T00:00:00+02:00</published><updated>2010-10-06T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-10-06:/pelican-a-simple-static-blog-generator-in-python.html</id><summary type="html">
|
||
<p>Those days, I&#8217;ve wrote a little python application to fit my blogging
|
||
needs. I&#8217;m an occasional blogger, a vim lover, I like restructured text
|
||
and DVCSes, so I&#8217;ve made a little tool that makes good use of all&nbsp;that.</p>
|
||
<p><a href="http://docs.getpelican.com">Pelican</a> (for calepin) is just a simple
|
||
tool …</p></summary><content type="html">
|
||
<p>Those days, I&#8217;ve wrote a little python application to fit my blogging
|
||
needs. I&#8217;m an occasional blogger, a vim lover, I like restructured text
|
||
and DVCSes, so I&#8217;ve made a little tool that makes good use of all&nbsp;that.</p>
|
||
<p><a href="http://docs.getpelican.com">Pelican</a> (for calepin) is just a simple
|
||
tool to generate your blog as static files, letting you using your
|
||
editor of choice (vim!). It&#8217;s easy to extend, and has a template
|
||
support (via&nbsp;jinja2).</p>
|
||
<p>I&#8217;ve made it to fit <em>my</em> needs. I hope it will fit yours, but maybe it
|
||
wont, and it have not be designed to feet everyone&#8217;s&nbsp;needs.</p>
|
||
<p>Need an example ? You&#8217;re looking at it ! This weblog is using pelican
|
||
to be generated, also for the atom&nbsp;feeds.</p>
|
||
<p>I&#8217;ve released it under <span class="caps">AGPL</span>, since I want all the modifications to be
|
||
profitable to all the&nbsp;users.</p>
|
||
<p>You can find a repository to fork at
|
||
<a href="https://github.com/getpelican/pelican/">https://github.com/getpelican/pelican/</a>. feel free to hack it&nbsp;!</p>
|
||
<p>If you just want to get started, use your installer of choice (pip,
|
||
easy_install, …) And then have a look to the help (pelican&nbsp;&#8212;help)</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pip<span class="w"> </span>install<span class="w"> </span>pelican
|
||
</code></pre></div>
|
||
|
||
<h2 id="usage">Usage</h2>
|
||
<p>Here&#8217;s a sample usage of&nbsp;pelican</p>
|
||
<div class="highlight"><pre><span></span><code>$<span class="w"> </span>pelican<span class="w"> </span>.
|
||
writing<span class="w"> </span>/home/alexis/projets/notmyidea.org/output/index.html
|
||
writing<span class="w"> </span>/home/alexis/projets/notmyidea.org/output/tags.html
|
||
writing<span class="w"> </span>/home/alexis/projets/notmyidea.org/output/categories.html
|
||
writing<span class="w"> </span>/home/alexis/projets/notmyidea.org/output/archives.html
|
||
writing<span class="w"> </span>/home/alexis/projets/notmyidea.org/output/category/python.html
|
||
writing
|
||
/home/alexis/projets/notmyidea.org/output/pelican-a-simple-static-blog-generator-in-python.html
|
||
Done<span class="w"> </span>!
|
||
</code></pre></div>
|
||
|
||
<p>You also can use the &#8212;help option for the command line to get more&nbsp;informations</p>
|
||
<div class="highlight"><pre><span></span><code><span class="nv">$pelican</span><span class="w"> </span>--help
|
||
usage:<span class="w"> </span>pelican<span class="w"> </span><span class="o">[</span>-h<span class="o">]</span><span class="w"> </span><span class="o">[</span>-t<span class="w"> </span>TEMPLATES<span class="o">]</span><span class="w"> </span><span class="o">[</span>-o<span class="w"> </span>OUTPUT<span class="o">]</span><span class="w"> </span><span class="o">[</span>-m<span class="w"> </span>MARKUP<span class="o">]</span><span class="w"> </span><span class="o">[</span>-s<span class="w"> </span>SETTINGS<span class="o">]</span><span class="w"> </span><span class="o">[</span>-b<span class="o">]</span>
|
||
<span class="w"> </span>path
|
||
|
||
A<span class="w"> </span>tool<span class="w"> </span>to<span class="w"> </span>generate<span class="w"> </span>a<span class="w"> </span>static<span class="w"> </span>blog,<span class="w"> </span>with<span class="w"> </span>restructured<span class="w"> </span>text<span class="w"> </span>input<span class="w"> </span>files.
|
||
|
||
positional<span class="w"> </span>arguments:
|
||
<span class="w"> </span>path<span class="w"> </span>Path<span class="w"> </span>where<span class="w"> </span>to<span class="w"> </span>find<span class="w"> </span>the<span class="w"> </span>content<span class="w"> </span>files<span class="w"> </span><span class="o">(</span>default<span class="w"> </span>is
|
||
<span class="w"> </span><span class="s2">&quot;content&quot;</span><span class="o">)</span>.
|
||
|
||
optional<span class="w"> </span>arguments:
|
||
<span class="w"> </span>-h,<span class="w"> </span>--help<span class="w"> </span>show<span class="w"> </span>this<span class="w"> </span><span class="nb">help</span><span class="w"> </span>message<span class="w"> </span>and<span class="w"> </span><span class="nb">exit</span>
|
||
<span class="w"> </span>-t<span class="w"> </span>TEMPLATES,<span class="w"> </span>--templates-path<span class="w"> </span>TEMPLATES
|
||
<span class="w"> </span>Path<span class="w"> </span>where<span class="w"> </span>to<span class="w"> </span>find<span class="w"> </span>the<span class="w"> </span>templates.<span class="w"> </span>If<span class="w"> </span>not<span class="w"> </span>specified,
|
||
<span class="w"> </span>will<span class="w"> </span>uses<span class="w"> </span>the<span class="w"> </span>ones<span class="w"> </span>included<span class="w"> </span>with<span class="w"> </span>pelican.
|
||
<span class="w"> </span>-o<span class="w"> </span>OUTPUT,<span class="w"> </span>--output<span class="w"> </span>OUTPUT
|
||
<span class="w"> </span>Where<span class="w"> </span>to<span class="w"> </span>output<span class="w"> </span>the<span class="w"> </span>generated<span class="w"> </span>files.<span class="w"> </span>If<span class="w"> </span>not<span class="w"> </span>specified,
|
||
<span class="w"> </span>a<span class="w"> </span>directory<span class="w"> </span>will<span class="w"> </span>be<span class="w"> </span>created,<span class="w"> </span>named<span class="w"> </span><span class="s2">&quot;output&quot;</span><span class="w"> </span><span class="k">in</span><span class="w"> </span>the
|
||
<span class="w"> </span>current<span class="w"> </span>path.
|
||
<span class="w"> </span>-m<span class="w"> </span>MARKUP,<span class="w"> </span>--markup<span class="w"> </span>MARKUP
|
||
<span class="w"> </span>the<span class="w"> </span>markup<span class="w"> </span>language<span class="w"> </span>to<span class="w"> </span>use.<span class="w"> </span>Currently<span class="w"> </span>only
|
||
<span class="w"> </span>ReSTreucturedtext<span class="w"> </span>is<span class="w"> </span>available.
|
||
<span class="w"> </span>-s<span class="w"> </span>SETTINGS,<span class="w"> </span>--settings<span class="w"> </span>SETTINGS
|
||
<span class="w"> </span>the<span class="w"> </span>settings<span class="w"> </span>of<span class="w"> </span>the<span class="w"> </span>application.<span class="w"> </span>Default<span class="w"> </span>to<span class="w"> </span>None.
|
||
<span class="w"> </span>-b,<span class="w"> </span>--debug
|
||
</code></pre></div>
|
||
|
||
<p>Enjoy&nbsp;:)</p></content><category term="code"></category></entry><entry><title>An amazing summer of code working on distutils2</title><link href="https://blog.notmyidea.org/an-amazing-summer-of-code-working-on-distutils2.html" rel="alternate"></link><published>2010-08-16T00:00:00+02:00</published><updated>2010-08-16T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-08-16:/an-amazing-summer-of-code-working-on-distutils2.html</id><summary type="html">
|
||
<p>The <a href="http://code.google.com/soc/">Google Summer of Code</a> I&#8217;ve spent
|
||
working on <a href="http://hg.python.org/distutils2/">distutils2</a> is over. It
|
||
was a really amazing experience, for many&nbsp;reasons.</p>
|
||
<p>First of all, we had a very good team, we were 5 students working on
|
||
distutils2: <a href="http://zubin71.wordpress.com">Zubin</a>,
|
||
<a href="http://wokslog.wordpress.com/">Éric</a>,
|
||
<a href="http://gsoc.djolonga.com/">Josip</a>,
|
||
<a href="http://konryd.blogspot.com/">Konrad</a> and me. In addition,
|
||
<a href="http://mouadino.blogspot.com/">Mouad</a> have worked on …</p></summary><content type="html">
|
||
<p>The <a href="http://code.google.com/soc/">Google Summer of Code</a> I&#8217;ve spent
|
||
working on <a href="http://hg.python.org/distutils2/">distutils2</a> is over. It
|
||
was a really amazing experience, for many&nbsp;reasons.</p>
|
||
<p>First of all, we had a very good team, we were 5 students working on
|
||
distutils2: <a href="http://zubin71.wordpress.com">Zubin</a>,
|
||
<a href="http://wokslog.wordpress.com/">Éric</a>,
|
||
<a href="http://gsoc.djolonga.com/">Josip</a>,
|
||
<a href="http://konryd.blogspot.com/">Konrad</a> and me. In addition,
|
||
<a href="http://mouadino.blogspot.com/">Mouad</a> have worked on the PyPI testing
|
||
infrastructure. You could find what each person have done on <a href="http://bitbucket.org/tarek/distutils2/wiki/GSoC_2010_teams">the wiki
|
||
page of
|
||
distutils2</a>.</p>
|
||
<p>We were in contact with each others really often, helping us when
|
||
possible (in #distutils), and were continuously aware of the state of
|
||
the work of each participant. This, in my opinion, have bring us in a
|
||
good&nbsp;shape.</p>
|
||
<p>Then, I&#8217;ve learned a lot. Python packaging was completely new to me at
|
||
the time of the GSoC start, and I was pretty unfamiliar with python good
|
||
practices too, as I&#8217;ve been introducing myself to python in the late&nbsp;2009.</p>
|
||
<p>I&#8217;ve recently looked at some python code I wrote just three months ago,
|
||
and I was amazed to think about many improvements to made on it. I guess
|
||
this is a good indicator of the path I&#8217;ve traveled since I wrote&nbsp;it.</p>
|
||
<p>This summer was awesome because I&#8217;ve learned about python good
|
||
practices, now having some strong
|
||
<a href="http://mercurial.selenic.com/">mercurial</a> knowledge, and I&#8217;ve seen a
|
||
little how the python community&nbsp;works.</p>
|
||
<p>Then, I would like to say a big thanks to all the mentors that have
|
||
hanged around while needed, on <span class="caps">IRC</span> or via mail, and especially my mentor
|
||
for this summer, <a href="http://tarek.ziade.org">Tarek Ziadé</a>.</p>
|
||
<p>Thanks a lot for your motivation, your leadership and your cheerfulness,
|
||
even with a new-born and a new&nbsp;work!</p>
|
||
<h2 id="why">Why&nbsp;?</h2>
|
||
<p>I wanted to work on python packaging because, as the time pass, we were
|
||
having a sort of complex tools in this field. Each one wanted to add
|
||
features to distutils, but not in a standard&nbsp;way.</p>
|
||
<p>Now, we have PEPs that describes some format we agreed on (see <span class="caps">PEP</span> 345),
|
||
and we wanted to have a tool on which users can base their code on,
|
||
that&#8217;s <a href="http://hg.python.org/distutils2/">distutils2</a>.</p>
|
||
<h2 id="my-job">My&nbsp;job</h2>
|
||
<p>I had to provide a way to crawl the PyPI indexes in a simple way, and do
|
||
some installation / uninstallation&nbsp;scripts.</p>
|
||
<p>All the work done is available in <a href="http://bitbucket.org/ametaireau/distutils2/">my bitbucket
|
||
repository</a>.</p>
|
||
<h3 id="crawling-the-pypi-indexes">Crawling the PyPI&nbsp;indexes</h3>
|
||
<p>There are two ways of requesting informations from the indexes: using
|
||
the &#8220;simple&#8221; index, that is a kind of <span class="caps">REST</span> index, and using <span class="caps">XML</span>-<span class="caps">RPC</span>.</p>
|
||
<p>I&#8217;ve done the two implementations, and a high level <span class="caps">API</span> to query those
|
||
twos. Basically, this supports the mirroring infrastructure defined in
|
||
<span class="caps">PEP</span> 381. So far, the work I&#8217;ve done is gonna be used in pip (they&#8217;ve
|
||
basically copy/paste the code, but this will change as soon as we get
|
||
something completely stable for distutils2), and that&#8217;s a good news, as
|
||
it was the main reason for what I&#8217;ve done&nbsp;that.</p>
|
||
<p>I&#8217;ve tried to have an unified <span class="caps">API</span> for the clients, to switch from one to
|
||
another implementation easily. I&#8217;m already thinking of adding others
|
||
crawlers to this stuff, and it was made to be&nbsp;extensible.</p>
|
||
<p>If you want to get more informations about the crawlers/PyPI clients,
|
||
please refer to the distutils2 documentation, especially <a href="http://distutils2.notmyidea.org/library/distutils2.index.html">the pages
|
||
about
|
||
indexes</a>.</p>
|
||
<p>You can find the changes I made about this in the
|
||
<a href="http://hg.python.org/distutils2/">distutils2</a> source code&nbsp;.</p>
|
||
<h3 id="installation-uninstallation-scripts">Installation / Uninstallation&nbsp;scripts</h3>
|
||
<p>Next step was to think about an installation script, and an uninstaller.
|
||
I&#8217;ve not done the uninstaller part, and it&#8217;s a smart part, as it&#8217;s
|
||
basically removing some files from the system, so I&#8217;ll probably do it in
|
||
a near&nbsp;future.</p>
|
||
<p><a href="http://hg.python.org/distutils2/">distutils2</a> provides a way to install
|
||
distributions, and to handle dependencies between releases. For now,
|
||
this support is only about the last version of the <span class="caps">METADATA</span> (1.2) (See,
|
||
the <span class="caps">PEP</span> 345), but I&#8217;m working on a compatibility layer for the old
|
||
metadata, and for the informations provided via <span class="caps">PIP</span> requires.txt, for&nbsp;instance.</p>
|
||
<h3 id="extra-work">Extra&nbsp;work</h3>
|
||
<p>Also, I&#8217;ve done some extra work. this&nbsp;includes:</p>
|
||
<ul>
|
||
<li>working on the <span class="caps">PEP</span> 345, and having some discussion about it (about
|
||
the names of some&nbsp;fields).</li>
|
||
<li>writing a PyPI server mock, useful for tests. you can find more
|
||
information about it on the
|
||
<a href="http://distutils.notmyidea.org">documentation</a>.</li>
|
||
</ul>
|
||
<h2 id="futures-plans">Futures&nbsp;plans</h2>
|
||
<p>As I said, I&#8217;ve enjoyed working on distutils2, and the people I&#8217;ve met
|
||
here are really pleasant to work with. So I <em>want</em> to continue
|
||
contributing on python, and especially on python packaging, because
|
||
there is still a lot of things to do in this scope, to get something
|
||
really&nbsp;usable.</p>
|
||
<p>I&#8217;m not plainly satisfied by the work I&#8217;ve done, so I&#8217;ll probably tweak
|
||
it a bit: the installer part is not yet completely finished, and I want
|
||
to add support for a real
|
||
<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"><span class="caps">REST</span></a>
|
||
index in the&nbsp;future.</p>
|
||
<p>We&#8217;ll talk again of this in the next months, probably, but we definitely
|
||
need a real
|
||
<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"><span class="caps">REST</span></a> <span class="caps">API</span>
|
||
for <a href="http://pypi.python.org">PyPI</a>, as the &#8220;simple&#8221; index <em>is</em> an ugly
|
||
hack, in my opinion. I&#8217;ll work on a serious proposition about this,
|
||
maybe involving <a href="http://couchdb.org">CouchDB</a>, as it seems to be a good
|
||
option for what we want&nbsp;here.</p>
|
||
<h2 id="issues">Issues</h2>
|
||
<p>I&#8217;ve encountered some issues during this summer. The main one is that&#8217;s
|
||
hard to work remotely, especially being in the same room that we live,
|
||
with others. I like to just think about a project with other people, a
|
||
paper and a pencil, no computers. This have been not so possible at the
|
||
start of the project, as I needed to read a lot of code to understand
|
||
the codebase, and then to read/write&nbsp;emails.</p>
|
||
<p>I&#8217;ve finally managed to work in an office, so good point for home/office&nbsp;separation.</p>
|
||
<p>I&#8217;d not planned there will be so a high number of emails to read, in
|
||
order to follow what&#8217;s up in the python world, and be a part of the
|
||
community seems to takes some times to read/write emails, especially for
|
||
those (like me) that arent so confortable with english (but this had
|
||
brought me some english fu&nbsp;!).</p>
|
||
<h2 id="thanks">Thanks&nbsp;!</h2>
|
||
<p>A big thanks to <a href="http://www.graine-libre.fr/">Graine Libre</a> and <a href="http://www.makina-corpus.com/">Makina
|
||
Corpus</a>, which has offered me to come
|
||
into their offices from time to time, to share they cheerfulness ! Many
|
||
thanks too to the Google Summer of Code program for setting up such an
|
||
initiative. If you&#8217;re a student, if you&#8217;re interested about <span class="caps">FOSS</span>, dont
|
||
hesitate any second, it&#8217;s a really good opportunity to work on
|
||
interesting&nbsp;projects!</p></content><category term="code"></category></entry><entry><title>Sprinting on distutils2 in Tours</title><link href="https://blog.notmyidea.org/sprinting-on-distutils2-in-tours.html" rel="alternate"></link><published>2010-07-10T00:00:00+02:00</published><updated>2010-07-10T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-07-10:/sprinting-on-distutils2-in-tours.html</id><summary type="html">
|
||
<ul>
|
||
<li>
|
||
<p>date<br>&nbsp;2010-07-06</p>
|
||
</li>
|
||
<li>
|
||
<p>category<br>&nbsp;tech</p>
|
||
</li>
|
||
</ul>
|
||
<p>Yesterday, as I was traveling to Tours, I&#8217;ve took some time to visit
|
||
Éric, another student who&#8217;s working on distutils2 this summer, as a
|
||
part of the GSoC. Basically, it was to take a drink, discuss a bit about
|
||
distutils2, our respective tasks and …</p></summary><content type="html">
|
||
<ul>
|
||
<li>
|
||
<p>date<br>&nbsp;2010-07-06</p>
|
||
</li>
|
||
<li>
|
||
<p>category<br>&nbsp;tech</p>
|
||
</li>
|
||
</ul>
|
||
<p>Yesterday, as I was traveling to Tours, I&#8217;ve took some time to visit
|
||
Éric, another student who&#8217;s working on distutils2 this summer, as a
|
||
part of the GSoC. Basically, it was to take a drink, discuss a bit about
|
||
distutils2, our respective tasks and general feelings, and to put a face
|
||
on a pseudonym. I&#8217;d really enjoyed this time, because Éric knows a lot
|
||
of things about mercurial and python good practices, and I&#8217;m eager to
|
||
learn about those. So, we have discussed about things, have not wrote so
|
||
much code, but have some things to propose so far, about documentation,
|
||
and I also provides here some bribes of conversations we&nbsp;had.</p>
|
||
<h2 id="documentation">Documentation</h2>
|
||
<p>While writing the PyPI simple index crawler documentation, I realized
|
||
that we miss some structure, or how-to about the documentation. Yep, you
|
||
read well. We lack documentation on how to make documentation. Heh.
|
||
We&#8217;re missing some rules to follow, and this lead to a not-so-structured
|
||
final documentation. We probably target three type of publics, and we
|
||
can split the documentation regarding&nbsp;those:</p>
|
||
<ul>
|
||
<li><strong>Packagers</strong> who want to distribute their&nbsp;softwares.</li>
|
||
<li><strong>End users</strong> who need to understand how to use end user commands,
|
||
like the&nbsp;installer/uninstaller</li>
|
||
<li><strong>packaging coders</strong> who <em>use</em> distutils2, as a base for building a
|
||
package&nbsp;manager.</li>
|
||
</ul>
|
||
<p>We also need to discuss about a pattern to follow while writing
|
||
documentation. How many parts do we need ? Where to put the <span class="caps">API</span>
|
||
description ? etc. That&#8217;s maybe seems to be not so important, but I
|
||
guess the readers would appreciate to have the same structure all along
|
||
distutils2&nbsp;documentation.</p>
|
||
<h2 id="mercurial">Mercurial</h2>
|
||
<p>I&#8217;m really <em>not</em> a mercurial power user. I use it on daily basis, but I
|
||
lack of basic knowledge about it. Big thanks Éric for sharing yours with
|
||
me, you&#8217;re of a great help. We have talked about some mercurial
|
||
extensions that seems to make the life simpler, while used the right
|
||
way. I&#8217;ve not used them so far, so consider this as a personal&nbsp;note.</p>
|
||
<ul>
|
||
<li>hg histedit, to edit the&nbsp;history</li>
|
||
<li>hg crecord, to select the changes to&nbsp;commit</li>
|
||
</ul>
|
||
<p>We have spent some time to review a merge I made sunday, to re-merge it,
|
||
and commit the changes as a new changeset. Awesome. These things make me
|
||
say I <strong>need</strong> to read <a href="http://hgbook.red-bean.com/read/">the hg book</a>,
|
||
and will do as soon as I got some spare time: mercurial seems to be
|
||
simply great. So &#8230; Great. I&#8217;m a powerful merger now&nbsp;!</p>
|
||
<h2 id="on-using-tools">On using&nbsp;tools</h2>
|
||
<p>Because we <em>also</em> are <em>hackers</em>, we have shared a bit our ways to code,
|
||
the tools we use, etc. Both of us were using vim, and I&#8217;ve discovered
|
||
vimdiff and hgtk, which will completely change the way I navigate into
|
||
the mercurial history. We aren&#8217;t &#8220;power users&#8221;, so we have learned from
|
||
each other about vim tips. You can find <a href="http://github.com/ametaireau/dotfiles">my dotfiles on
|
||
github</a>, if it could help.
|
||
They&#8217;re not perfect, and not intended to be, because changing all the
|
||
time, as I learn. Don&#8217;t hesitate to have a look, and to propose
|
||
enhancements if you have&nbsp;!</p>
|
||
<h2 id="on-being-pythonic">On being&nbsp;pythonic</h2>
|
||
<p>My background as an old Java user disserves me so far, as the paradigms
|
||
are not the same while coding in python. Hard to find the more pythonic
|
||
way to do, and sometimes hard to unlearn my way to think about software
|
||
engineering. Well, it seems that the only solution is to read code, and
|
||
to re-read import this from times to times ! <a href="http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html">Coding like a
|
||
pythonista</a>
|
||
seems to be a must-read, so, I know what to&nbsp;do.</p>
|
||
<h2 id="conclusion">Conclusion</h2>
|
||
<p>It was really great. Next time, we&#8217;ll need to focus a bit more on
|
||
distutils2, and to have a bullet list of things to do, but days like
|
||
this one are opportunities to catch ! We&#8217;ll probably do another sprint
|
||
in a few weeks, stay tuned&nbsp;!</p></content><category term="code"></category></entry><entry><title>Introducing the distutils2 index crawlers</title><link href="https://blog.notmyidea.org/introducing-the-distutils2-index-crawlers.html" rel="alternate"></link><published>2010-07-06T00:00:00+02:00</published><updated>2010-07-06T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-07-06:/introducing-the-distutils2-index-crawlers.html</id><summary type="html">
|
||
<p>I&#8217;m working for about a month for distutils2, even if I was being a bit
|
||
busy (as I had some class courses and exams to work&nbsp;on)</p>
|
||
<p>I&#8217;ll try do sum-up my general feelings here, and the work I&#8217;ve made so
|
||
far. You can also find, if …</p></summary><content type="html">
|
||
<p>I&#8217;m working for about a month for distutils2, even if I was being a bit
|
||
busy (as I had some class courses and exams to work&nbsp;on)</p>
|
||
<p>I&#8217;ll try do sum-up my general feelings here, and the work I&#8217;ve made so
|
||
far. You can also find, if you&#8217;re interested, my weekly summaries in <a href="http://wiki.notmyidea.org/distutils2_schedule">a
|
||
dedicated wiki page</a>.</p>
|
||
<h2 id="general-feelings">General&nbsp;feelings</h2>
|
||
<p>First, and it&#8217;s a really important point, the GSoC is going very well,
|
||
for me as for other students, at least from my perspective. It&#8217;s a
|
||
pleasure to work with such enthusiast people, as this make the global
|
||
atmosphere very pleasant to&nbsp;live.</p>
|
||
<p>First of all, I&#8217;ve spent time to read the existing codebase, and to
|
||
understand what we&#8217;re going to do, and what&#8217;s the rationale to do&nbsp;so.</p>
|
||
<p>It&#8217;s really clear for me now: what we&#8217;re building is the foundations of
|
||
a packaging infrastructure in python. The fact is that many projects
|
||
co-exists, and comes all with their good concepts. Distutils2 tries to
|
||
take the interesting parts of all, and to provide it in the python
|
||
standard libs, respecting the recently written <span class="caps">PEP</span> about&nbsp;packaging.</p>
|
||
<p>With distutils2, it will be simpler to make &#8220;things&#8221; compatible. So if
|
||
you think about a new way to deal with distributions and packaging in
|
||
python, you can use the Distutils2 APIs to do&nbsp;so.</p>
|
||
<h2 id="tasks">Tasks</h2>
|
||
<p>My main task while working on distutils2 is to provide an installation
|
||
and an un-installation command, as described in <span class="caps">PEP</span> 376. For this, I
|
||
first need to get informations about the existing distributions (what&#8217;s
|
||
their version, name, metadata, dependencies,&nbsp;etc.)</p>
|
||
<p>The main index, you probably know and use, is PyPI. You can access it at
|
||
<a href="http://pypi.python.org">http://pypi.python.org</a>.</p>
|
||
<h2 id="pypi-index-crawling">PyPI index&nbsp;crawling</h2>
|
||
<p>There is two ways to get these informations from PyPI: using the simple
|
||
<span class="caps">API</span>, or via xml-rpc&nbsp;calls.</p>
|
||
<p>A goal was to use the version specifiers defined
|
||
in<a href="http://www.python.org/dev/peps/pep-0345/"><span class="caps">PEP</span> 345</a> and to provides a
|
||
way to sort the grabbed distributions depending our needs, to pick the
|
||
version we&nbsp;want/need.</p>
|
||
<h3 id="using-the-simple-api">Using the simple <span class="caps">API</span></h3>
|
||
<p>The simple <span class="caps">API</span> is composed of <span class="caps">HTML</span> pages you can access at
|
||
<a href="http://pypi.python.org/simple/">http://pypi.python.org/simple/</a>.</p>
|
||
<p>Distribute and Setuptools already provides a crawler for that, but it
|
||
deals with their internal mechanisms, and I found that the code was not
|
||
so clear as I want, that&#8217;s why I&#8217;ve preferred to pick up the good ideas,
|
||
and some implementation details, plus re-thinking the global&nbsp;architecture.</p>
|
||
<p>The rules are simple: each project have a dedicated page, which allows
|
||
us to get informations&nbsp;about:</p>
|
||
<ul>
|
||
<li>the distribution download locations (for some&nbsp;versions)</li>
|
||
<li>homepage&nbsp;links</li>
|
||
<li>some other useful informations, as the bugtracker address, for&nbsp;instance.</li>
|
||
</ul>
|
||
<p>If you want to find all the distributions of the &#8220;EggsAndSpam&#8221; project,
|
||
you could do the following (do not take so attention to the names here,
|
||
as the <span class="caps">API</span> will probably change a&nbsp;bit):</p>
|
||
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="n">index</span> <span class="o">=</span> <span class="n">SimpleIndex</span><span class="p">()</span>
|
||
<span class="o">&gt;&gt;&gt;</span> <span class="n">index</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&quot;EggsAndSpam&quot;</span><span class="p">)</span>
|
||
<span class="p">[</span><span class="n">EggsAndSpam</span> <span class="mf">1.1</span><span class="p">,</span> <span class="n">EggsAndSpam</span> <span class="mf">1.2</span><span class="p">,</span> <span class="n">EggsAndSpam</span> <span class="mf">1.3</span><span class="p">]</span>
|
||
</code></pre></div>
|
||
|
||
<p>We also could use version&nbsp;specifiers:</p>
|
||
<div class="highlight"><pre><span></span><code><span class="o">&gt;&gt;&gt;</span> <span class="n">index</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&quot;EggsAndSpam (&lt; =1.2)&quot;</span><span class="p">)</span>
|
||
<span class="p">[</span><span class="n">EggsAndSpam</span> <span class="mf">1.1</span><span class="p">,</span> <span class="n">EggsAndSpam</span> <span class="mf">1.2</span><span class="p">]</span>
|
||
</code></pre></div>
|
||
|
||
<p>Internally, what&#8217;s done here is the&nbsp;following:</p>
|
||
<ul>
|
||
<li>it process the <a href="http://pypi.python.org/simple/FooBar/">http://pypi.python.org/simple/FooBar/</a> page,
|
||
searching for download&nbsp;URLs.</li>
|
||
<li>for each found distribution download <span class="caps">URL</span>, it creates an object,
|
||
containing informations about the project name, the version and the
|
||
<span class="caps">URL</span> where the archive&nbsp;remains.</li>
|
||
<li>it sort the found distributions, using version numbers. The default
|
||
behavior here is to prefer source distributions (over binary ones),
|
||
and to rely on the last &#8220;final&#8221; distribution (rather than beta,
|
||
alpha etc.&nbsp;ones)</li>
|
||
</ul>
|
||
<p>So, nothing hard or difficult&nbsp;here.</p>
|
||
<p>We provides a bunch of other features, like relying on the new PyPI
|
||
mirroring infrastructure or filter the found distributions by some
|
||
criterias. If you&#8217;re curious, please browse the <a href="http://distutils2.notmyidea.org/">distutils2
|
||
documentation</a>.</p>
|
||
<h3 id="using-xml-rpc">Using&nbsp;xml-rpc</h3>
|
||
<p>We also can make some xmlrpc calls to retreive informations from PyPI.
|
||
It&#8217;s a really more reliable way to get informations from from the index
|
||
(as it&#8217;s just the index that provides the informations), but cost
|
||
processes on the PyPI distant&nbsp;server.</p>
|
||
<p>For now, this way of querying the xmlrpc client is not available on
|
||
Distutils2, as I&#8217;m working on it. The main pieces are already present
|
||
(I&#8217;ll reuse some work I&#8217;ve made from the SimpleIndex querying, and <a href="http://github.com/ametaireau/pypiclient">some
|
||
code already set up</a>), what I
|
||
need to do is to provide a xml-rpc PyPI mock server, and that&#8217;s on what
|
||
I&#8217;m actually working&nbsp;on.</p>
|
||
<h2 id="processes">Processes</h2>
|
||
<p>For now, I&#8217;m trying to follow the &#8220;documentation, then test, then code&#8221;
|
||
path, and that seems to be really needed while working with a community.
|
||
Code is hard to read/understand, compared to documentation, and it&#8217;s
|
||
easier to&nbsp;change.</p>
|
||
<p>While writing the simple index crawling work, I must have done this to
|
||
avoid some changes on the <span class="caps">API</span>, and some loss of&nbsp;time.</p>
|
||
<p>Also, I&#8217;ve set up <a href="http://wiki.notmyidea.org/distutils2_schedule">a
|
||
schedule</a>, and the goal
|
||
is to be sure everything will be ready in time, for the end of the
|
||
summer. (And now, I need to learn to follow schedules&nbsp;&#8230;)</p></content><category term="code"></category></entry><entry><title>Use Restructured Text (ReST) to power your presentations</title><link href="https://blog.notmyidea.org/use-restructured-text-rest-to-power-your-presentations.html" rel="alternate"></link><published>2010-06-25T00:00:00+02:00</published><updated>2010-06-25T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-06-25:/use-restructured-text-rest-to-power-your-presentations.html</id><summary type="html">
|
||
<ul>
|
||
<li>
|
||
<p>date<br>&nbsp;2010-06-25</p>
|
||
</li>
|
||
<li>
|
||
<p>category<br>&nbsp;tech</p>
|
||
</li>
|
||
</ul>
|
||
<p>Wednesday, we give a presentation, with some friends, about the CouchDB
|
||
Database, to <a href="http://www.toulibre.org">the Toulouse local <span class="caps">LUG</span></a>. Thanks a
|
||
lot to all the presents for being there, it was a pleasure to talk about
|
||
this topic with you. Too bad the season is over now an …</p></summary><content type="html">
|
||
<ul>
|
||
<li>
|
||
<p>date<br>&nbsp;2010-06-25</p>
|
||
</li>
|
||
<li>
|
||
<p>category<br>&nbsp;tech</p>
|
||
</li>
|
||
</ul>
|
||
<p>Wednesday, we give a presentation, with some friends, about the CouchDB
|
||
Database, to <a href="http://www.toulibre.org">the Toulouse local <span class="caps">LUG</span></a>. Thanks a
|
||
lot to all the presents for being there, it was a pleasure to talk about
|
||
this topic with you. Too bad the season is over now an I quit Toulouse
|
||
next&nbsp;year.</p>
|
||
<p>During our brainstorming about the topic, we used some paper, and we
|
||
wanted to make a presentation the simpler way. First thing that come to
|
||
my mind was using <a href="http://docutils.sourceforge.net/rst.html">restructured
|
||
text</a>, so I&#8217;ve wrote a simple
|
||
file containing our different bullet points. In fact, there is quite
|
||
nothing to do then, to have a working&nbsp;presentation.</p>
|
||
<p>So far, I&#8217;ve used <a href="http://code.google.com/p/rst2pdf/">the rst2pdf
|
||
program</a>, and a simple template, to
|
||
generate output. It&#8217;s probably simple to have similar results using
|
||
latex + beamer, I&#8217;ll try this next time, but as I&#8217;m not familiar with
|
||
latex syntax, restructured text was a great&nbsp;option.</p>
|
||
<p>Here are <a href="http://files.lolnet.org/alexis/rst-presentations/couchdb/couchdb.pdf">the final <span class="caps">PDF</span>
|
||
output</a>,
|
||
<a href="http://files.lolnet.org/alexis/rst-presentations/couchdb/couchdb.rst">Rhe ReST
|
||
source</a>,
|
||
<a href="http://files.lolnet.org/alexis/rst-presentations/slides.style">the theme
|
||
used</a>,
|
||
and the command line to generate the <span class="caps">PDF</span>:</p>
|
||
<div class="highlight"><pre><span></span><code>rst2pdf couchdb.rst -b1 -s ../slides.style
|
||
</code></pre></div></content><category term="code"></category></entry><entry><title>first week working on distutils2</title><link href="https://blog.notmyidea.org/first-week-working-on-distutils2.html" rel="alternate"></link><published>2010-06-04T00:00:00+02:00</published><updated>2010-06-04T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-06-04:/first-week-working-on-distutils2.html</id><summary type="html">
|
||
<p>As I&#8217;ve been working on <a href="http://hg.python.org/distutils2/">Distutils2</a>
|
||
during the past week, taking part of the
|
||
<a href="http://code.google.com/intl/fr/soc/"><span class="caps">GSOC</span></a> program, here is a short
|
||
summary of what I&#8217;ve done so&nbsp;far.</p>
|
||
<p>As my courses are not over yet, I&#8217;ve not worked as much as I wanted, and
|
||
this will continues until …</p></summary><content type="html">
|
||
<p>As I&#8217;ve been working on <a href="http://hg.python.org/distutils2/">Distutils2</a>
|
||
during the past week, taking part of the
|
||
<a href="http://code.google.com/intl/fr/soc/"><span class="caps">GSOC</span></a> program, here is a short
|
||
summary of what I&#8217;ve done so&nbsp;far.</p>
|
||
<p>As my courses are not over yet, I&#8217;ve not worked as much as I wanted, and
|
||
this will continues until the end of June. My main tasks are about
|
||
making installation and uninstallation commands, to have a simple way to
|
||
install distributions via
|
||
<a href="http://hg.python.org/distutils2/">Distutils2</a>.</p>
|
||
<p>To do this, we need to rely on informations provided by the Python
|
||
Package Index (<a href="http://pypi.python.org/">PyPI</a>), and there is at least
|
||
two ways to retreive informations from here: <span class="caps">XML</span>-<span class="caps">RPC</span> and the &#8220;simple&#8221;
|
||
<span class="caps">API</span>.</p>
|
||
<p>So, I&#8217;ve been working on porting some
|
||
<a href="http://bitbucket.org/tarek/distribute/">Distribute</a> related stuff to
|
||
<a href="http://hg.python.org/distutils2/">Distutils2</a>, cutting off all non
|
||
distutils&#8217; things, as we do not want to depend from Distribute&#8217;s
|
||
internals. My main work has been about reading the whole code, writing
|
||
tests about this and making those tests&nbsp;possible.</p>
|
||
<p>In fact, there was a need of a pypi mocked server, and, after reading
|
||
and introducing myself to the distutils behaviors and code, I&#8217;ve taken
|
||
some time to improve the work <a href="http://bitbucket.org/konrad">Konrad</a>
|
||
makes about this&nbsp;mock.</p>
|
||
<h2 id="a-pypi-server-mock">A PyPI Server&nbsp;mock</h2>
|
||
<p>The mock is embeded in a thread, to make it available during the tests,
|
||
in a non blocking way. We first used <a href="http://wsgi.org"><span class="caps">WSGI</span></a> and
|
||
<a href="http://docs.python.org/library/wsgiref.html">wsgiref</a> in order control
|
||
what to serve, and to log the requests made to the server, but finally
|
||
realised that <a href="http://docs.python.org/library/wsgiref.html">wsgiref</a> is
|
||
not python 2.4 compatible (and we <em>need</em> to be python 2.4 compatible in&nbsp;Distutils2).</p>
|
||
<p>So, we switched to
|
||
<a href="http://docs.python.org/library/basehttpserver.html">BaseHTTPServer</a> and
|
||
<a href="http://docs.python.org/library/simplehttpserver.html">SimpleHTTPServer</a>,
|
||
and updated our tests accordingly. It&#8217;s been an opportunity to realize
|
||
that <a href="http://wsgi.org"><span class="caps">WSGI</span></a> has been a great step forward for making
|
||
<span class="caps">HTTP</span> servers, and expose a really simplest way to discuss with <span class="caps">HTTP</span>&nbsp;!</p>
|
||
<p>You can find <a href="http://bitbucket.org/ametaireau/distutils2/changesets">the modifications I
|
||
made</a>, and the
|
||
<a href="http://bitbucket.org/ametaireau/distutils2/src/tip/docs/source/test_framework.rst">related
|
||
docs</a>
|
||
about this on <a href="http://bitbucket.org/ametaireau/distutils2/">my bitbucket distutils2
|
||
clone</a>.</p>
|
||
<h2 id="the-pypi-simple-api">The PyPI Simple <span class="caps">API</span></h2>
|
||
<p>So, back to the main problematic: make a python library to access and
|
||
request information stored on PyPI, via the simple <span class="caps">API</span>. As I said, I&#8217;ve
|
||
just grabbed the work made from
|
||
<a href="http://bitbucket.org/tarek/distribute/">Distribute</a>, and played a bit
|
||
with, in order to view what are the different use cases, and started to
|
||
write the related&nbsp;tests.</p>
|
||
<h2 id="the-work-to-come">The work to&nbsp;come</h2>
|
||
<p>So, once all use cases covered with tests, I&#8217;ll rewrite a bit the
|
||
grabbed code, and do some software design work (to not expose all things
|
||
as privates methods, have a clear <span class="caps">API</span>, and other things like this), then
|
||
update the tests accordingly and write a documentation to make this&nbsp;clear.</p>
|
||
<p>Next step is to a little client, as I&#8217;ve <a href="http://github.com/ametaireau/pypiclient">already started
|
||
here</a> I&#8217;ll take you updated&nbsp;!</p></content><category term="code"></category></entry><entry><title>A Distutils2 GSoC</title><link href="https://blog.notmyidea.org/a-distutils2-gsoc.html" rel="alternate"></link><published>2010-05-01T00:00:00+02:00</published><updated>2010-05-01T00:00:00+02:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-05-01:/a-distutils2-gsoc.html</id><summary type="html">
|
||
<p><span class="caps">WOW</span>. I&#8217;ve been accepted to be a part of the <a href="http://code.google.com/intl/fr/soc/">Google Summer Of
|
||
Code</a> program, and will work on
|
||
<a href="http://python.org/">python</a> <a href="http://hg.python.org/distutils2/">distutils2</a>, with <a href="http://pygsoc.wordpress.com/">a</a> <a href="http://konryd.blogspot.com/">lot</a> <a href="http://ziade.org/">of</a> (intersting !) <a href="http://zubin71.wordpress.com/">people</a>.</p>
|
||
<blockquote>
|
||
<p>So, it&#8217;s about building the successor of Distutils2, ie. &#8220;the python
|
||
package manager&#8221;. Today, there is too many ways to package …</p></blockquote></summary><content type="html">
|
||
<p><span class="caps">WOW</span>. I&#8217;ve been accepted to be a part of the <a href="http://code.google.com/intl/fr/soc/">Google Summer Of
|
||
Code</a> program, and will work on
|
||
<a href="http://python.org/">python</a> <a href="http://hg.python.org/distutils2/">distutils2</a>, with <a href="http://pygsoc.wordpress.com/">a</a> <a href="http://konryd.blogspot.com/">lot</a> <a href="http://ziade.org/">of</a> (intersting !) <a href="http://zubin71.wordpress.com/">people</a>.</p>
|
||
<blockquote>
|
||
<p>So, it&#8217;s about building the successor of Distutils2, ie. &#8220;the python
|
||
package manager&#8221;. Today, there is too many ways to package a python
|
||
application (pip, setuptools, distribute, distutils, etc.) so there is
|
||
a huge effort to make in order to make all this packaging stuff
|
||
interoperable, as pointed out by
|
||
the <a href="http://www.python.org/dev/peps/pep-0376/"><span class="caps">PEP</span> 376</a>.</p>
|
||
</blockquote>
|
||
<p>In more details, I&#8217;m going to work on the Installer / Uninstaller features of Distutils2, and on a PyPI <span class="caps">XML</span>-<span class="caps">RPC</span> client for distutils2. Here are the already defined&nbsp;tasks:</p>
|
||
<ul>
|
||
<li>Implement Distutils2 APIs described in <span class="caps">PEP</span>&nbsp;376.</li>
|
||
<li>Add the uninstall&nbsp;command.</li>
|
||
<li>think about a basic installer / uninstaller script. (with deps) &#8212;
|
||
similar to&nbsp;pip/easy_install</li>
|
||
<li>in a pypi&nbsp;subpackage;</li>
|
||
<li>Integrate a module similar to setuptools&#8217;&nbsp;package_index&#8217;</li>
|
||
<li>PyPI <span class="caps">XML</span>-<span class="caps">RPC</span> client for distutils 2:
|
||
<a href="http://bugs.python.org/issue8190">http://bugs.python.org/issue8190</a></li>
|
||
</ul>
|
||
<p>As I&#8217;m relatively new to python, I&#8217;ll need some extra work in order to apply all good practice, among other things that can make a developper-life joyful. I&#8217;ll post here, each week, my advancement, and my tought about python and especialy python packaging&nbsp;world.</p></content><category term="code"></category></entry><entry><title>Le temps des grâces, courrez-y !</title><link href="https://blog.notmyidea.org/le-temps-des-graces-courrez-y.html" rel="alternate"></link><published>2010-03-28T00:00:00+01:00</published><updated>2010-03-28T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-03-28:/le-temps-des-graces-courrez-y.html</id><summary type="html">
|
||
<p>Ouf, notre <a href="http://www.reseaugrappe.org">semaine de l&#8217;environnement</a>
|
||
s&#8217;est terminée, après un peu de neige et un brin de soleil quand il en
|
||
fallait&nbsp;!</p>
|
||
<p>Ce fut l&#8217;occasion de rencontrer beaucoup de gens biens, et de regarder
|
||
d&#8217;un peu plus près toutes ces problématiques qui mériteraient à elles
|
||
seules, chacune …</p></summary><content type="html">
|
||
<p>Ouf, notre <a href="http://www.reseaugrappe.org">semaine de l&#8217;environnement</a>
|
||
s&#8217;est terminée, après un peu de neige et un brin de soleil quand il en
|
||
fallait&nbsp;!</p>
|
||
<p>Ce fut l&#8217;occasion de rencontrer beaucoup de gens biens, et de regarder
|
||
d&#8217;un peu plus près toutes ces problématiques qui mériteraient à elles
|
||
seules, chacune un billet. Après un répis d&#8217;une semaine, pour récupérer
|
||
des folies organisatrices (c&#8217;est ça qui fait du bien, ceci dit &#8212; les
|
||
folies, pas le repos), je me retrouve de nouveau sur ces mêms
|
||
réflexions, grâce aux journées organisées par <a href="http://www.fne.asso.fr/">France Nature
|
||
Environnement</a>, qui proposaient ce jeudi soir
|
||
une projection de &#8220;Le temps des grâces&#8221;, un documentaire sur&nbsp;l&#8217;agriculture.</p>
|
||
<p>Parce que depuis 60 ans, il est pratiqué le remembrement des parcelles à
|
||
gogo, parce que nos sols deviennent completement morts à cause des
|
||
tonnes d&#8217;intrants qu&#8217;on leur fait absorber, et parce que les
|
||
exploitations s&#8217;agrandissent sans en finir pour tenter de réagir façe à
|
||
un marché financier toujours plus insaisissable, mené de très loin par
|
||
la <span class="caps">PAC</span>, il fallait un film pour en parler. C&#8217;est ce que fait &#8220;le temps
|
||
des grâçes&#8221;, avec un bon sens et une facilité à faire passer des
|
||
messages, qu&#8217;on ne peut&nbsp;qu&#8217;applaudir.</p>
|
||
<p>Malheureusement il s&#8217;agissait de la dernière diffusion à <a href="http://www.cinemas-utopia.org/toulouse/">L&#8217;Utopia de
|
||
Toulouse</a>&#8230; Si vous en avez
|
||
l&#8217;occasion, sautez dessus et profitez le temps de ces 2 heures, ou vous
|
||
pourrez écouter à la fois des discours d&#8217;agronomes, d&#8217;agriculteurs, de
|
||
chercheurs et bien d&#8217;autres, qui dressent un constat pas si brillant de
|
||
notre agriculture. On n&#8217;est pas sorti de l&#8217;auberge, enfin, c&#8217;est&nbsp;l&#8217;expression.</p>
|
||
<p>Je vous laisse avec le synopsis et une bande&nbsp;annonce.</p>
|
||
<blockquote>
|
||
<p>Une enquête documentaire sur le monde agricole français aujourd&#8217;hui à
|
||
travers de nombreux récits : agriculteurs, chercheurs, agronomes,
|
||
écrivains&#8230; Un monde qui parvient à résister aux bouleversements qui
|
||
le frappent -économiques, scientifiques, sociaux - et qui, bon gré mal
|
||
gré, continue d&#8217;entretenir les liens entre générations. Un monde au
|
||
centre d&#8217;interrogations majeures sur&nbsp;l&#8217;avenir.</p>
|
||
</blockquote>
|
||
<p>Ainsi qu&#8217;un commentaire que je ne peux m&#8217;empécher de relayer, trouvé sur
|
||
allocine.fr (oui, vous savez, ce site rempli de&nbsp;pubs).</p>
|
||
<blockquote>
|
||
<p>Le temps des grâces c&#8217;est je pense le plus grand film traitant de
|
||
l&#8217;écologie en tant que documentaire ou en sujet principal, on y
|
||
apprend une multitude de choses, on en ressort en colère contre le
|
||
système, le film propose différents points de vues, ici on a pas de
|
||
voix off moralisatrice à deux balles avec des gros titres bien
|
||
surlignés pour que même les beaufs matant <span class="caps">TF1</span> puissent comprendre,
|
||
ici même si ça reste accessible au citoyen lambda, le film ne fait pas
|
||
de compromis avec le monde agroalimentaire, il ose dénoncer les
|
||
filière d&#8217;agronomie qui apprennent pas les bonnes choses à leurs
|
||
étudiants, aux lobbys de cette agro-industrie qui n&#8217;en fait qu&#8217;à sa
|
||
tête pour amasser de l&#8217;argent, cette tendance à tout uniformiser et
|
||
détruire… Franchement j&#8217;ai trouvé ça génial de bout en bout,
|
||
captivant, on explore cette campagne française, on comprend les
|
||
dilemmes des paysants. Le film n&#8217;étant pas opposé à la modernité, ni
|
||
même réactionnaire, il propose juste un constat alarmant du monde
|
||
agricole français, tout en proposant des alternatives qui pourraient
|
||
être utilisée, si les pouvoirs publics lâchaient un peu la main des
|
||
lobbys. Passionnant,&nbsp;vraiment.</p>
|
||
</blockquote>
|
||
<p>Courrez-y, je vous&nbsp;dis.</p></content><category term="journal"></category></entry><entry><title>Semaine de l’environnement: La consommation étudiante</title><link href="https://blog.notmyidea.org/semaine-de-lenvironnement-la-consommation-etudiante.html" rel="alternate"></link><published>2010-02-24T00:00:00+01:00</published><updated>2010-02-24T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2010-02-24:/semaine-de-lenvironnement-la-consommation-etudiante.html</id><summary type="html">
|
||
<p>Les acteurs associatifs sont bien souvent moteurs des critiques de nos
|
||
sociétés. Je pense à <a href="http://www.framasoft.net/">Framasoft</a>, à <a href="http://www.laquadrature.net/">la
|
||
Quadrature du net</a> ou à <a href="http://www.arsindustrialis.org/">Ars
|
||
Industrialis</a> (dans le domaine de la
|
||
science et de l&#8217;informatique), mais aussi <a href="http://www.amisdelaterre.org/">aux Amis de la
|
||
Terre</a>, à <a href="http://www.attac.org/"><span class="caps">ATTAC</span></a>
|
||
(dans le domaine de l&#8217;environnement …</p></summary><content type="html">
|
||
<p>Les acteurs associatifs sont bien souvent moteurs des critiques de nos
|
||
sociétés. Je pense à <a href="http://www.framasoft.net/">Framasoft</a>, à <a href="http://www.laquadrature.net/">la
|
||
Quadrature du net</a> ou à <a href="http://www.arsindustrialis.org/">Ars
|
||
Industrialis</a> (dans le domaine de la
|
||
science et de l&#8217;informatique), mais aussi <a href="http://www.amisdelaterre.org/">aux Amis de la
|
||
Terre</a>, à <a href="http://www.attac.org/"><span class="caps">ATTAC</span></a>
|
||
(dans le domaine de l&#8217;environnement entres autres), et a tout un tas
|
||
d&#8217;autres associations que je ne peux pas citer ici exhaustivement&#8230; Ce
|
||
sont eux qui sont porteurs de messages alternatifs, et qui sont les
|
||
initiateurs de débats publics, qui permettent de faire avancer des
|
||
thématiques aussi importantes que le logiciel libre ou la protection de&nbsp;l&#8217;environnement.</p>
|
||
<p>Dans cette optique, depuis près de 3 ans (déjà !), au sein du <a href="http://www.reseaugrappe.org">réseau
|
||
<span class="caps">GRAPPE</span></a>, on <em>essaye</em> d&#8217;aborder des
|
||
thématiques qui touchent de près ou de loin à l&#8217;environnement, parce
|
||
que c&#8217;est un sujet qui nous importe et nous passionne. L&#8217;année dernière,
|
||
c&#8217;était l&#8217;alimentation étudiante, ce qui à abouti à la publication de
|
||
<a href="http://public.reseaugrappe.org/alimentation.pdf">la revue &#8220;les étudiants se mettent à
|
||
table&#8221;</a>. Cette année
|
||
c&#8217;est la consommation étudiante qui est au&nbsp;programme.</p>
|
||
<h2 id="la-consommation-etudiante">La consommation étudiante&nbsp;?</h2>
|
||
<p>L&#8217;idée principale de cette étude est de tenter de faire une analyse de
|
||
la &#8220;société de consommation&#8221;, souvent questionnée par les étudiants et
|
||
par d&#8217;autres, et de jeter un œil sur le rapport des étudiants à cette
|
||
société: Quoi et comment consomment-ils ? Les universités et les écoles
|
||
ne poussent-elles pas d’une certaine manière les étudiants à la
|
||
consommation ? Quelles sont les alternatives face aux dérives de
|
||
surconsommation&nbsp;?</p>
|
||
<blockquote>
|
||
<p>Analyse des pratiques, réflexions et mobilisations des étudiants en
|
||
termes de consommation seront réalisés pour comprendre leur modes de
|
||
vie, mais aussi leurs attentes, leurs propositions sur cette&nbsp;thématique</p>
|
||
</blockquote>
|
||
<h2 id="la-semaine-de-lenvironnement">La semaine de l&#8217;environnement&nbsp;!</h2>
|
||
<p>A travers l&#8217;ensemble des villes du réseau, des projections de films et
|
||
des débats auront donc lieu sur ce thème, lors de la semaine de
|
||
l&#8217;environnement 2010, qui se déroulera d&#8217;ailleurs durant le mois de Mars
|
||
<a href="http://www.reseaugrappe.org/la-semaine-de-lenvironnement-programme/">partout en
|
||
france</a>,
|
||
et <strong>du 6 au 14 Mars sur Toulouse</strong>. <a href="http://docs.notmyidea.org/sde/prog-toulouse.pdf">Jetez un oeil au
|
||
programme</a> ! Avec pour
|
||
objectif de sonder un peu le ressenti des étudiants en terme de
|
||
consommation, nous avons mis en place <a href="http://spreadsheets.google.com/viewform?formkey=dHV2bVllS2lWbzhyV3NBN3NUbi1TM2c6MA">un questionnaire en
|
||
ligne</a>,
|
||
que vous pouvez compléter en une petite 10aine de minutes, n&#8217;hésitez pas
|
||
! <a href="http://www.reseaugrappe.org/consommation/">La page sur la consommation étudiante sur le site du
|
||
<span class="caps">GRAPPE</span></a></p></content><category term="journal"></category></entry><entry><title>Python ? go !</title><link href="https://blog.notmyidea.org/python-go.html" rel="alternate"></link><published>2009-12-17T00:00:00+01:00</published><updated>2009-12-17T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2009-12-17:/python-go.html</id><summary type="html">
|
||
<p>Cela fait maintenant un peu plus d&#8217;un mois que je travaille sur un
|
||
projet en <a href="http://www.djangoproject.org">django</a>, et que,
|
||
nécessairement, je me forme à <a href="http://python.org/">Python</a>. Je prends
|
||
un plaisir non dissimulé à découvrir ce langage (et à l&#8217;utiliser), qui
|
||
ne cesse de me surprendre. Les premiers mots qui me …</p></summary><content type="html">
|
||
<p>Cela fait maintenant un peu plus d&#8217;un mois que je travaille sur un
|
||
projet en <a href="http://www.djangoproject.org">django</a>, et que,
|
||
nécessairement, je me forme à <a href="http://python.org/">Python</a>. Je prends
|
||
un plaisir non dissimulé à découvrir ce langage (et à l&#8217;utiliser), qui
|
||
ne cesse de me surprendre. Les premiers mots qui me viennent à l&#8217;esprit
|
||
à propos de Python, sont &#8220;logique&#8221; et &#8220;simple&#8221;. Et pourtant puissant
|
||
pour autant. Je ne manque d&#8217;ailleurs pas une occasion pour faire un peu
|
||
d&#8217;<em>évangélisation</em> auprès des quelques personnes qui veulent bien&nbsp;m&#8217;écouter.</p>
|
||
<h2 id="the-zen-of-python">The Zen of&nbsp;Python</h2>
|
||
<p>Avant toute autre chose, je pense utile de citer Tim Peters, et <a href="http://www.python.org/dev/peps/pep-0020/">le
|
||
<span class="caps">PEP20</span></a>, qui constituent une
|
||
très bonne introduction au langage, qui prends la forme d&#8217;un <em>easter
|
||
egg</em> présent dans&nbsp;python</p>
|
||
<div class="highlight"><pre><span></span><code>&gt;&gt;&gt;<span class="w"> </span>import<span class="w"> </span>this
|
||
The<span class="w"> </span>Zen<span class="w"> </span>of<span class="w"> </span>Python,<span class="w"> </span>by<span class="w"> </span>Tim<span class="w"> </span>Peters
|
||
|
||
Beautiful<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>ugly.
|
||
Explicit<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>implicit.
|
||
Simple<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>complex.
|
||
Complex<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>complicated.
|
||
Flat<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>nested.
|
||
Sparse<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>dense.
|
||
Readability<span class="w"> </span>counts.
|
||
Special<span class="w"> </span>cases<span class="w"> </span>aren<span class="s1">&#39;t special enough to break the rules.</span>
|
||
<span class="s1">Although practicality beats purity.</span>
|
||
<span class="s1">Errors should never pass silently.</span>
|
||
<span class="s1">Unless explicitly silenced.</span>
|
||
<span class="s1">In the face of ambiguity, refuse the temptation to guess.</span>
|
||
<span class="s1">There should be one-- and preferably only one --obvious way to do it.</span>
|
||
<span class="s1">Although that way may not be obvious at first unless you&#39;</span>re<span class="w"> </span>Dutch.
|
||
Now<span class="w"> </span>is<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>never.
|
||
Although<span class="w"> </span>never<span class="w"> </span>is<span class="w"> </span>often<span class="w"> </span>better<span class="w"> </span>than<span class="w"> </span>*right*<span class="w"> </span>now.
|
||
If<span class="w"> </span>the<span class="w"> </span>implementation<span class="w"> </span>is<span class="w"> </span>hard<span class="w"> </span>to<span class="w"> </span>explain,<span class="w"> </span>it<span class="s1">&#39;s a bad idea.</span>
|
||
<span class="s1">If the implementation is easy to explain, it may be a good idea.</span>
|
||
<span class="s1">Namespaces are one honking great idea -- let&#39;</span>s<span class="w"> </span><span class="k">do</span><span class="w"> </span>more<span class="w"> </span>of<span class="w"> </span>those!
|
||
</code></pre></div>
|
||
|
||
<p>J&#8217;ai la vague impression que c&#8217;est ce que j&#8217;ai toujours cherché à faire
|
||
en <span class="caps">PHP</span>, et particulièrement dans <a href="http://www.spiral-project.org">le framework
|
||
Spiral</a>, mais en ajoutant ces concepts
|
||
dans une sur-couche au langage. Ici, c&#8217;est directement de <em>l&#8217;esprit</em> de
|
||
python qu&#8217;il s&#8217;agit, ce qui signifie que la plupart des bibliothèques
|
||
python suivent ces concepts. Elle est pas belle la vie&nbsp;?</p>
|
||
<h2 id="comment-commencer-et-par-ou">Comment commencer, et par ou&nbsp;?</h2>
|
||
<p>Pour ma part, j&#8217;ai commencé par la lecture de quelques livres et
|
||
articles intéressants, qui constituent une bonne entrée en matière sur
|
||
le sujet (La liste n&#8217;est bien évidemment pas exhaustive et vos
|
||
commentaires sont les bienvenus)&nbsp;:</p>
|
||
<ul>
|
||
<li><a href="http://diveintopython.adrahon.org/">Dive into&nbsp;python</a></li>
|
||
<li><a href="http://www.swaroopch.com/notes/Python_fr:Table_des_Matières">A byte of&nbsp;python</a></li>
|
||
<li><a href="http://www.amazon.fr/Python-Petit-guide-lusage-développeur/dp/2100508830">Python: petit guide à l&#8217;usage du développeur
|
||
agile</a>
|
||
de <a href="http://tarekziade.wordpress.com/">Tarek&nbsp;Ziadé</a></li>
|
||
<li><a href="http://docs.python.org/index.html">La documentation officielle
|
||
python</a>, bien sûr&nbsp;!</li>
|
||
<li><a href="http://video.pycon.fr/videos/pycon-fr-2009/">Les vidéos du
|
||
pyconfr 2009</a>!</li>
|
||
<li>Un peu de temps, et une console python ouverte&nbsp;:)</li>
|
||
</ul>
|
||
<p>J&#8217;essaye par ailleurs de partager au maximum les ressources que je
|
||
trouve de temps à autres, que ce soit <a href="http://www.twitter.com/ametaireau">via
|
||
twitter</a> ou <a href="http://delicious.com/ametaireau">via mon compte
|
||
delicious</a>. Allez jeter un œil <a href="http://delicious.com/ametaireau/python">au tag
|
||
python</a> sur mon profil, peut
|
||
être que vous trouverez des choses intéressantes, qui&nbsp;sait!</p>
|
||
<h2 id="un-python-sexy">Un python&nbsp;sexy</h2>
|
||
<p>Quelques fonctionnalités qui devraient vous mettre l&#8217;eau à la&nbsp;bouche:</p>
|
||
<ul>
|
||
<li><a href="http://docs.python.org/library/stdtypes.html#comparisons">Le chaînage des opérateurs de
|
||
comparaison</a>
|
||
est possible (a\&lt;b \&lt;c dans une&nbsp;condition)</li>
|
||
<li>Assignation de valeurs multiples (il est possible de faire a,b,c =
|
||
1,2,3 par&nbsp;exemple)</li>
|
||
<li><a href="http://docs.python.org/tutorial/datastructures.html">Les listes</a>
|
||
sont simples à manipuler&nbsp;!</li>
|
||
<li>Les <a href="http://docs.python.org/tutorial/datastructures.html#list-comprehensions">list
|
||
comprehension</a>,
|
||
ou comment faire des opérations complexes sur les listes, de manière&nbsp;simple.</li>
|
||
<li>Les
|
||
<a href="http://docs.python.org/library/doctest.html?highlight=doctest">doctests</a>:
|
||
ou comment faire des tests directement dans la documentation de vos
|
||
classes, tout en la documentant avec de vrais&nbsp;exemples.</li>
|
||
<li>Les
|
||
<a href="http://www.python.org/doc/essays/metaclasses/meta-vladimir.txt">métaclasses</a>,
|
||
ou comment contrôler la manière dont les classes se&nbsp;construisent</li>
|
||
<li>Python est <a href="http://wiki.python.org/moin/Why%20is%20Python%20a%20dynamic%20language%20and%20also%20a%20strongly%20typed%20language">un langage à typage fort
|
||
dynamique</a>:
|
||
c&#8217;est ce qui m&#8217;agaçait avec <span class="caps">PHP</span> qui est un langage à typage faible&nbsp;dynamique.</li>
|
||
</ul>
|
||
<p>Cous pouvez également aller regarder <a href="http://video.pycon.fr/videos/free/53/">l&#8217;atelier donné par Victor Stinner
|
||
durant le Pyconfr 09</a>. Have fun&nbsp;!</p></content><category term="code"></category></entry><entry><title>AMAP + Média = Paniers bio à 5e ?!</title><link href="https://blog.notmyidea.org/amap-media-paniers-bio-a-5e.html" rel="alternate"></link><published>2009-11-11T00:00:00+01:00</published><updated>2009-11-11T00:00:00+01:00</updated><author><name></name></author><id>tag:blog.notmyidea.org,2009-11-11:/amap-media-paniers-bio-a-5e.html</id><summary type="html">
|
||
<p>Le raccourci me semble un peu rapide. Et pourtant, il est emprunté bien
|
||
trop souvent. La dernière <em>mes-utilisation</em> que j&#8217;ai à décrier est celle
|
||
d&#8217;un reportage télé, passé sur France 2 vendredi 23 Octobre (<a href="http://docs.notmyidea.org/amap/amap-fr2.avi">voir la
|
||
vidéo</a>), ou on parles de
|
||
<a href="http://amap.zest.free.fr">l&#8217;<span class="caps">AMAP</span> étudiante Zest</a>.</p>
|
||
<p>Malgré tout le …</p></summary><content type="html">
|
||
<p>Le raccourci me semble un peu rapide. Et pourtant, il est emprunté bien
|
||
trop souvent. La dernière <em>mes-utilisation</em> que j&#8217;ai à décrier est celle
|
||
d&#8217;un reportage télé, passé sur France 2 vendredi 23 Octobre (<a href="http://docs.notmyidea.org/amap/amap-fr2.avi">voir la
|
||
vidéo</a>), ou on parles de
|
||
<a href="http://amap.zest.free.fr">l&#8217;<span class="caps">AMAP</span> étudiante Zest</a>.</p>
|
||
<p>Malgré tout le temps passé à expliquer que justement, l&#8217;<span class="caps">AMAP</span> c&#8217;est avant
|
||
tout, pour nous, une notion de solidarité envers les agriculteurs,
|
||
malgré le fait que le message soit plus profond que simplement aller
|
||
acheter du bio (ça, c&#8217;est possible aussi en supermarché), malgré le fait
|
||
qu&#8217;il s&#8217;agisse en fait d&#8217;une remise en cause plus profonde de la
|
||
société, les journalistes n&#8217;ont choisi de prendre que les quelques
|
||
secondes qui leurs convenaient, celles qui ne faisaient pas tache, celle
|
||
ou je dis que &#8220;l&#8217;<span class="caps">AMAP</span> permet aux étudiants de réapprendre à cuisiner,
|
||
plutôt que de manger des nouilles et de se faire des plats réchauffés&#8221;.
|
||
Bien sur, je l&#8217;ai dit et je le pense d&#8217;ailleurs, là n&#8217;est pas le
|
||
problème, mais mon message n&#8217;était pas celui&nbsp;là.</p>
|
||
<p>Jamais, dans les quelques minutes du reportage, on ne dit ce que <span class="caps">AMAP</span>
|
||
signifie: Association de <strong>Maintien</strong> d&#8217;une Agriculture <strong>Paysanne</strong>. On
|
||
ne parles même pas des agriculteurs ! C&#8217;est simplement plus facile pour
|
||
les étudiants de venir récupérer leurs paniers, puisque les points de
|
||
distribution sont sur les facs, et en plus ça ne coute que 5 euros !&nbsp;&#8230;</p>
|
||
<p>Alors je crois bon de rappeler que L&#8217;<span class="caps">AMAP</span> n&#8217;est pas seulement un
|
||
service, c&#8217;est un engagement. Sur 5 mois, un engagement solidaire, c&#8217;est
|
||
la donnée principale de l&#8217;équation, celle sans quoi ça ne peut
|
||
fonctionner. Par le biais de cette <span class="caps">AMAP</span>, on essaye de montrer que
|
||
d&#8217;autres agricultures sont possibles, que la solidarité c&#8217;est bien réel,
|
||
et qu&#8217;il est possible de sortir du <em>tout, tout de suite</em>.</p>
|
||
<p>Mais bon, apparemment, ça passe pas bien à la&nbsp;télé.</p></content><category term="journal"></category></entry></feed> |