<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jujens' blog</title><link href="//www.jujens.eu/" rel="alternate"></link><link href="//www.jujens.eu/feeds/all.atom.xml" rel="self"></link><id>//www.jujens.eu/</id><updated>2020-09-17T00:00:00+02:00</updated><entry><title>Server tips</title><link href="//www.jujens.eu/posts/en/2020/Sep/17/server/" rel="alternate"></link><published>2020-09-17T00:00:00+02:00</published><updated>2020-09-17T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-09-17:/posts/en/2020/Sep/17/server/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#start-systemd-services-automatically-for-a-user" id="id1"&gt;Start systemd services automatically for a user&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="start-systemd-services-automatically-for-a-user"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Start systemd services automatically for a user&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By default sysemtd services linked to a user – created with &lt;tt class="docutils literal"&gt;systemctl &lt;span class="pre"&gt;--user&lt;/span&gt; enable &lt;span class="pre"&gt;--now&lt;/span&gt; service&lt;/tt&gt; for instance – are only started after the first login of the user.
To start them when the server starts, you …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#start-systemd-services-automatically-for-a-user" id="id1"&gt;Start systemd services automatically for a user&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="start-systemd-services-automatically-for-a-user"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Start systemd services automatically for a user&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By default sysemtd services linked to a user – created with &lt;tt class="docutils literal"&gt;systemctl &lt;span class="pre"&gt;--user&lt;/span&gt; enable &lt;span class="pre"&gt;--now&lt;/span&gt; service&lt;/tt&gt; for instance – are only started after the first login of the user.
To start them when the server starts, you must enable lingering for the user with (as root):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
loginctl enable-linger USER
&lt;/pre&gt;
&lt;p&gt;You can also soo the lingering status for a user with (as root):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
loginctl show-user USER --property Linger
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://wiki.archlinux.org/index.php/Systemd/User#Automatic_start-up_of_systemd_user_instances"&gt;https://wiki.archlinux.org/index.php/Systemd/User#Automatic_start-up_of_systemd_user_instances&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category></entry><entry><title>Make JS code communicate with a ServiceWorker</title><link href="//www.jujens.eu/posts/en/2020/Aug/18/serviceworker-js-communication/" rel="alternate"></link><published>2020-08-18T00:00:00+02:00</published><updated>2020-08-18T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-08-18:/posts/en/2020/Aug/18/serviceworker-js-communication/</id><summary type="html">&lt;p&gt;If you need to send data from your JS code to your ServiceWorker, you can do it like this:&lt;/p&gt;
&lt;pre class="code JavaScript literal-block"&gt;
&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./sw.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;registration&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Some message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can then rely on this code in the ServiceWorker to read the message:&lt;/p&gt;
&lt;pre class="code JavaScript literal-block"&gt;
&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;If you need to send data from your JS code to your ServiceWorker, you can do it like this:&lt;/p&gt;
&lt;pre class="code JavaScript literal-block"&gt;
&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./sw.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;registration&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Some message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can then rely on this code in the ServiceWorker to read the message:&lt;/p&gt;
&lt;pre class="code JavaScript literal-block"&gt;
&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This will log: Some message
&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category><category term="Web"></category><category term="ServiceWorker"></category></entry><entry><title>Aurelia Store and Immer</title><link href="//www.jujens.eu/posts/en/2020/Aug/09/aurelia-store-immerjs/" rel="alternate"></link><published>2020-08-09T00:00:00+02:00</published><updated>2020-08-09T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-08-09:/posts/en/2020/Aug/09/aurelia-store-immerjs/</id><summary type="html">&lt;p&gt;I spoke last year of Aurelia store in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2019/Aug/24/aurelia-store/"&gt;this article&lt;/a&gt;
At the time, it wasn't possible to combine Aurelia Store and &lt;a class="reference external" href="https://immerjs.github.io/immer/docs/introduction"&gt;Immer&lt;/a&gt;.
The root cause of the issue was fixed in the latest version of Immer (7.0), so we can now combine both.&lt;/p&gt;
&lt;p&gt;Let's study how to do this …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I spoke last year of Aurelia store in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2019/Aug/24/aurelia-store/"&gt;this article&lt;/a&gt;
At the time, it wasn't possible to combine Aurelia Store and &lt;a class="reference external" href="https://immerjs.github.io/immer/docs/introduction"&gt;Immer&lt;/a&gt;.
The root cause of the issue was fixed in the latest version of Immer (7.0), so we can now combine both.&lt;/p&gt;
&lt;p&gt;Let's study how to do this:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Install immer with &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;--save&lt;/span&gt; &lt;span class="pre"&gt;immer&amp;#64;^7.0.7&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;yarn add &lt;span class="pre"&gt;immer&amp;#64;^7.0.7&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Because we need Aurelia to update the state when it's used in component to add some observers, we must disable immer's &lt;a class="reference external" href="https://immerjs.github.io/immer/docs/freezing"&gt;auto-freezing&lt;/a&gt;. You can do this in &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt; with:&lt;/p&gt;
&lt;pre class="code JavaScript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setAutoFreeze&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'immer'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// This is required to allow Aurelia to add its observer on objects in the state.
&lt;/span&gt;&lt;span class="nx"&gt;setAutoFreeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Update you actions to use &lt;tt class="docutils literal"&gt;produce&lt;/tt&gt;. This will allow you to modify the state directly without mutating it. This way, the history features of the store will be preserved. For a simple example:&lt;/p&gt;
&lt;pre class="code JavaScript literal-block"&gt;
&lt;span class="c1"&gt;// Before.
&lt;/span&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;selectBackend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectedBackend&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SelectableBackend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedBackend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedBackend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// After
&lt;/span&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;selectBackend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectedBackend&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SelectableBackend&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedBackend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selectedBackend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Thanks to immer, you don't have to copy the state explicitly, immer will create a new state based on your modification automatically.
The &lt;tt class="docutils literal"&gt;produce&lt;/tt&gt; function takes a function that will receive the draft of the state you can modify as first argument and all other arguments passed to you action as extra arguments.
So the function you need to pass to &lt;tt class="docutils literal"&gt;produce&lt;/tt&gt; takes the same arguments as a standard action.
You still need to be aware and pay attention to some details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;All the objects in the store are changed so immer can track the changes without modifying the original objects. This means that this won't work:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;deleteArticle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Will return -1 because article is not in the articles array, it's proxied version is.
&lt;/span&gt;    &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;indexOfArticleToDelete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Only the state will be a &amp;quot;draft&amp;quot; (to use immer terminology) and can be modified directly. If you were to modify other argument, you would mutate them. And if they are in the store, you would update them the store as well. So this won't work as expected and will mutate the object:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;markAsRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;produce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For both these issues, you need to first find the proper object in the draft state and apply the modification to it.
You can view an example &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/-/blob/5a962d4fdd0c06ac809a9689c401d63de99a09a9/src/store/rss-backends-actions.ts#L119"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want more detail, you can check &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/-/commit/5a962d4fdd0c06ac809a9689c401d63de99a09a9"&gt;this commit&lt;/a&gt; of one of my project when I updated my actions to use immer.&lt;/p&gt;
&lt;p&gt;As noted by &lt;a class="reference external" href="https://github.com/zewa666"&gt;Vildan Softic&lt;/a&gt; (the creator of Aurelia Store), you can organize how you update the state differently to update the state correctly while keeping things clear without requiring immer.
You can see an example &lt;a class="reference external" href="https://github.com/zewa666/enforted/blob/master/src/store/actions/commands.ts#L62"&gt;here&lt;/a&gt;.
Many thanks to him for pointing that out and giving me some pointer to correctly test Aurelia Store with Immer.&lt;/p&gt;
&lt;p&gt;So while I think it's really nice to be able to use Immer, whether to use it or not highly depends on your programming style and on whether you can afford adding yet another library to your project (immer is about 15kB minified which is tiny, but it adds up with the rest).&lt;/p&gt;
</content><category term="Aurelia"></category><category term="JavaScript"></category><category term="TypeScript"></category><category term="Aurelia"></category><category term="RxJS"></category></entry><entry><title>Testing a clojure web framework</title><link href="//www.jujens.eu/posts/en/2020/Aug/02/testing-clojure-luminus/" rel="alternate"></link><published>2020-08-02T00:00:00+02:00</published><updated>2020-08-02T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-08-02:/posts/en/2020/Aug/02/testing-clojure-luminus/</id><summary type="html">&lt;p class="first last"&gt;An opinion about Clojure, Luminus and Reagent after doing a test project with these technologies.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;After learning &lt;a class="reference external" href="https://clojure.org/"&gt;Clojure&lt;/a&gt; thanks to the awesome book &lt;a class="reference external" href="https://www.braveclojure.com/"&gt;Clojure for the Brave and True&lt;/a&gt; I decided to test some web programing with the language to practice a bit.&lt;/p&gt;
&lt;p&gt;Before dwelling on this experience, I'd like to say a few words about the language itself.
I heard about the language when I was still completing my masters degree in 2014 or 2015.
I didn't gave it much attention back then.
Later, I noticed that &lt;a class="reference external" href="https://blog.cleancoder.com/"&gt;Robert C. Martin&lt;/a&gt; (author of the book &lt;a class="reference external" href="https://www.goodreads.com/book/show/3735293-clean-code"&gt;Clean Code&lt;/a&gt; among other books) talked about it and seemed to enjoy the language.
Since I respect his technical opinion, it raised my interest again and I look a bit into it and bought the book &lt;em&gt;Clojure for the Brave and True&lt;/em&gt; which then sat on my bookshelf for a couple of years.
Until the middle of last year when I decided to seriously look at functional programming and finally went through the book.&lt;/p&gt;
&lt;p&gt;This was mind blowing!
In addition to the great qualities of the book who made the learning journey really fun, I found the language itself to be really well designed and interesting to learn.
I like the notion than almost everything is a function (the example with the simple &lt;tt class="docutils literal"&gt;+&lt;/tt&gt; function at the beginning of the book really hooked me up), the way it handles &amp;quot;polymorphism&amp;quot;, atoms and references…
I also had to change perspective and get used to everything being immutable which requires lot of thinking at first but forced me to reconsider many things about my daily programing practice.
The fact that the book comes with many exercices after each chapter is a great plus to sharpen the reader's skills.
It's a great learning experience and I do encourage you to learn the language.
I must confess I still have issues with the syntax (it's a LISP after all with lots of parentheses everywhere) and how to organize my code.
But I don't practice much, so I guess it's normal.&lt;/p&gt;
&lt;p&gt;Moving on to web development and Luminus.
In order to practice and to do something that ressembles what I do daily (web development), I decided to write a small website using the language.
I looked around for a library/framework to help me in this endeavour and found &lt;a class="reference external" href="https://luminusweb.com/"&gt;Luminus&lt;/a&gt; which looked very good: the documentation is very detailed and it has a great getting started.
It also has a lot of template to create projects with different setup easily (like choose which database you want or to bootstrap the frontend for you).
I also dwelled a bit on frontend development with &lt;a class="reference external" href="https://clojurescript.org/"&gt;ClojureScript&lt;/a&gt; (the version of Clojure designed to run in the browser) and &lt;a class="reference external" href="https://github.com/reagent-project/reagent"&gt;Reagent&lt;/a&gt;, a library written in ClojureScript that leverages React to create dynamic interfaces.
After some quick tests, I knew I would be able to do what I wanted.&lt;/p&gt;
&lt;p&gt;My goal was to create a site to help manage various competitions.
In the end, I mostly played with Reagent and coded the home page of the site as well as the detail pages for each competitions.
I initially wanted to add a form to add competitions and a search feature but gave up due to lack of time.
The frontend was entirely done in Reagent and communicated with the backend thanks to REST.
The code is available &lt;a class="reference external" href="https://gitlab.com/Jenselme/cljgolf"&gt;here&lt;/a&gt; if you want to take a look at it.&lt;/p&gt;
&lt;p&gt;I liked how the frontend and backend can work together and never require a full server restart.
The code, from both the frontend and the backend, is updated via hot updates which makes the developer experience very fluid.
That's also very important since the server is very slow to start, without this auto-reload feature, I think the development experience would be very poor.
It also means I almost never had to fully reload the page.
That was really pleasing.&lt;/p&gt;
&lt;p&gt;On the unpleasing side of things: I decided to use a SQL database (as I saw while making the getting started).
From what I tested, that's where the framework doesn't shine: I had to write SQL for each query I had to make which doesn't seem very flexible to me.
Maybe because I'm too used to the Django ORM by now to revert to raw SQL for every requests.
I also had to restart the server each time I edited a query for my changes to be taken into account.
That was adding to the pain I felt when writing SQL queries and one of the reason I decided not to take more time on the project: it would require even more queries.
I looked for ways to avoid this, but didn't find anything (I may not have looked hard enough) and still thinks the framework should handle this for me.
What's strange is other than that, the experience is very fluid and hot reload work perfectly.
This made me think that it's also partially why MongoDB is so popular: all you need is to send JSON to the server and all languages have good tools to do this, mostly Clojure with its emphasis on data and using maps &lt;a class="footnote-reference" href="#what-are-maps" id="id1"&gt;[1]&lt;/a&gt; everywhere.
No need for someone to build and maintain the complex piece of technology that is an ORM.&lt;/p&gt;
&lt;p&gt;All in all, I'm satisfied with what I did and intend to continue trying stuff with Clojure.
If I do something else, I'll probably use MongoDB to avoid SQL altogether.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="what-are-maps" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Also known as dict in Python.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content><category term="Blog"></category><category term="Clojure"></category><category term="Luminus"></category><category term="Reagent"></category></entry><entry><title>Retrospective on my biggest personal project</title><link href="//www.jujens.eu/posts/en/2020/Jul/19/last-run-retrospective/" rel="alternate"></link><published>2020-07-19T00:00:00+02:00</published><updated>2020-07-19T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-07-19:/posts/en/2020/Jul/19/last-run-retrospective/</id><summary type="html">&lt;p class="first last"&gt;A retrospective on my biggest and longest personal project.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Today I'd like to look back at my longest (and biggest) personal project and what I learned along the way.
The project is now called &lt;em&gt;Last Run&lt;/em&gt; (but was named &lt;em&gt;Arena of Titans&lt;/em&gt; when we started).
It's a board game adapted for web usage.
It went live a few month ago and is available &lt;a class="reference external" href="https://www.last-run.com/"&gt;here&lt;/a&gt;.
The project is also entirely Open Source under the AGPLv3 license with the code source hosted on &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/"&gt;gitlab&lt;/a&gt;.
If you play and have feedback, let me know!
We are on social media or you can leave a comment here.&lt;/p&gt;
&lt;p&gt;I started the project in 2014 when I was completing my studies in Centrale Marseille, a French engineering school.
At the time, we were 4 on the project: the creator of the game, myself and two other developers.
This project was accepted as our final project assignment which was a great way to combine passion and usefulness.
Now we are three: the creator of the game who does a bit of development but is mostly working on the gameplay, myself as the main developer and a new developer who participates from time to time.&lt;/p&gt;
&lt;p&gt;The original version of the game was written in Java and AngularJS.
I remember I looked at &lt;a class="reference external" href="https://wicket.apache.org/"&gt;Apache Wicket&lt;/a&gt; and &lt;a class="reference external" href="https://vaadin.com/"&gt;Vaadin&lt;/a&gt; to do everything in Java, including the frontend.
This idea was influenced by a fellow student (but not teammate) who really liked Vaadin (and maybe still does).
Eventually, after some tests, it became clear the project wasn't really fitting into this model (don't ask me exactly why, it was years ago) and I settled on AngularJS (for the best I think).
At this time, the frontend did HTTP requests to the API because it was easier this way given what we knew and all players had to play on the same computer because it was easier for us and we didn't really know how to update other browsers even if they were connected to the same API.
Since HTTP requests should be stateless, I stored the game state in Redis which is the only original technical decision that remained over the years.
It was also the early days of Docker, which looked cool and could allow me to avoid installing Java on my server, so I initially deployed the app with it.
It was a bit painful (mostly because I did it at the very end of the project so the examiners could see it on the web) but it was interesting and fun to do.&lt;/p&gt;
&lt;p&gt;After graduation, the creator of the game and myself still wanted to work on the game to improve it while the other members of the team didn't and left.
I tried to improve the Java version, mostly to add proper multiplayer and to rely on websocket to provide real time, two-way communication with the API.
However, I've always been a Python guy and choose Java for the first version of the game only because it was more convenient for other team members.
I was also a bit tired of the ES5/AngularJS frontend and wanted to switch to ES6 (we were in 2015 at this time, JS already made its &amp;quot;revolution&amp;quot; with ES6).
The fact that ES5/AngularJS was what I was using at work also influenced my decision: I wanted to play with something new and different.&lt;/p&gt;
&lt;p&gt;So, I decided to rewrite the thing.
I tested few options in the backend:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Go: it felt complicated given what I knew and what I was trying to achieve. Furthermore, I dislike the type system, maybe because I came from a Java and Python background. My main paint point was that I was already using sets in the algorithm and since Go doesn't have sets in the standard library, I needed an extra package. And since Go doesn't support generics, I had to allow any type in my sets which defeats the purpose of a type system in my opinion. That's the equivalent of doing &lt;tt class="docutils literal"&gt;Set&amp;lt;Object&amp;gt;&lt;/tt&gt; in Java which is strongly discouraged.&lt;/li&gt;
&lt;li&gt;NodeJS: it felt very young and was lacking some modern APIs (like &lt;tt class="docutils literal"&gt;Set&lt;/tt&gt;) at the time. That would have required to either not use them or to somehow transpile the code which I wasn't willing to do. And the future of the project wasn't very clear at the time with the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Node.js#Io.js"&gt;io.js&lt;/a&gt; fork.&lt;/li&gt;
&lt;li&gt;Python: I was able to do all I wanted and it's a language I always used and loved. I was also using it at work, so it made sense to use it here too. Did I really need to test anything else you may ask? For the sake of testing and experimenting I may answer. I choose (and still use today) the &lt;a class="reference external" href="https://autobahn.readthedocs.io/en/latest/"&gt;Autobahn library&lt;/a&gt; for websocket communication. What I found interesting was that I could use it with &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; (which landed in the standard library in Python 3.4, the Python version of the time) which seemed like the way to go for async programing. That was a very goo choice, mostly in Python 3.5 when the &lt;tt class="docutils literal"&gt;async&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;await&lt;/tt&gt; keywords were introduced and completely made &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; the way to go for new async code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the frontend, I tried several options (VueJS wasn't really a thing at this time, so I didn't tested it):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Angular 2 (now just named Angular): it seemed like the logical choice since the existing app was written in AngularJS. The framework was in Beta at the time. I really didn't like the experience it provided: it felt very complicated and cluttered. I also encounter several problems with the router which didn't invite me to trust the framework. Even after reading a book about it a few months later, after it was officially released, it still felt over-engineered and not that clear to me. So I was glad I discarded it.&lt;/li&gt;
&lt;li&gt;Ember: it felt nice but limiting because of how it handles data. I didn't really adhere to its ways of doing things. Still felt like a strong framework.&lt;/li&gt;
&lt;li&gt;React: it didn't left much of an impression at the time. I don't think it was that popular back then and it felt like I would lack some structure and need to add many things by myself (which is consistent with the fact it's more a rendering library than a framework).&lt;/li&gt;
&lt;li&gt;Aurelia: that's the framework I immediately loved. It felt like an updated and simplified (in a good sense) version of AngularJS. I saw how I could transfer and improve my existing practices of working with AngularJS. I still think it is an under-appreciated framework that deserves to be more known.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So after these tests, I decided to rewrite the project in Python with Autobahn using &lt;tt class="docutils literal"&gt;asyncio&lt;/tt&gt; and Aurelia in the frontend.
I started in July 2015 and I think I completed a first version during the rest of the summer.
Of course the project evolved over time:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;I added CI to run my tests automatically.&lt;/li&gt;
&lt;li&gt;I add many linters (both in the backend and in the frontend). I also added &lt;a class="reference external" href="https://prettier.io/"&gt;prettier&lt;/a&gt; and &lt;a class="reference external" href="https://black.readthedocs.io/en/stable/"&gt;black&lt;/a&gt; to automatically format my code. I check formatting with a pre-commit hook in git and even let PyCharm reformat the code on save.&lt;/li&gt;
&lt;li&gt;I switched to &lt;a class="reference external" href="https://pre-commit.com/"&gt;pre-commit&lt;/a&gt; to manage my pre-commit hooks.&lt;/li&gt;
&lt;li&gt;I switched to &lt;a class="reference external" href="https://aurelia.io/docs/plugins/store"&gt;Aurelia store&lt;/a&gt; to manage the application state. I initially relied on a custom service but relying on a more complete solution made sense in the end. See &lt;a class="reference external" href="//www.jujens.eu/posts/en/2019/Aug/24/aurelia-store/"&gt;this article&lt;/a&gt; to learn more about this process.&lt;/li&gt;
&lt;li&gt;I added validation in the API. Initially I always assumed I was given proper data (I guess I was young and unafraid back then). By the way, in Python, &lt;a class="reference external" href="https://docs.python-cerberus.org/en/stable/"&gt;Cerberus&lt;/a&gt; is a very good library to do that!&lt;/li&gt;
&lt;li&gt;I'm stricter in my usage of functions: initially I embraced the flexibility of Python a bit to much and allowed both &lt;tt class="docutils literal"&gt;Card&lt;/tt&gt; object and tuple &lt;tt class="docutils literal"&gt;(card_name, card_color)&lt;/tt&gt; (which allowed me to find the proper &lt;tt class="docutils literal"&gt;Card&lt;/tt&gt; object) to be passed around which made the code more complex and more fragile. I'm stricter now in how I define the interfaces of my functions.&lt;/li&gt;
&lt;li&gt;I reduce various subjects of tech debts and simplified many portions of the code thanks to all the things I learned in Python, JS and programming in general over the last 6 years.&lt;/li&gt;
&lt;li&gt;I changed a few times of package managers and bundles for the frontend. See &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Jul/04/aurelia-wepack/"&gt;this article&lt;/a&gt; to learn more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One very important point I haven't talked about yet is the deploy process.
That's another area where I learned much over these years!
I had a server even as a student, so I used it even for the earliest versions of the game.
I don't remember exactly how I deployed the first version of the app using docker though.
I think I just exported the image as a &lt;tt class="docutils literal"&gt;tar.gz&lt;/tt&gt; and imported it on the server with some kind of custom Bash script.
Since it was the early days of docker which wasn't very stable at the time, I switched to standard &lt;a class="reference external" href="https://uwsgi-docs.readthedocs.io/en/latest/"&gt;uwsgi&lt;/a&gt; directly on the server and packaging all Python dependencies as RPM packages installed on the system (luckily I didn't have much of those because it takes a lot of time!).
Later, when I wanted to switch to a more powerful server, I think I switched back to docker because it made dependency management and deploys easier.
At this stage, I was still using custom Bash scripts to build and deploy images.
The front was deployed with Rsync.
It was a bit weird, not always stable but globally worked.
After that, I switched jobs and discovered &lt;a class="reference external" href="https://docs.ansible.com/ansible/latest/"&gt;Ansible&lt;/a&gt; as a tool to deploy stuff.
Since it way more stable and complete than what I could create by hand, I switched to it a few years back.
That's where I am now: a bunch of Ansible playbooks to build and deploy both the frontend and the backend.
The backend runs in docker and the frontend is served directly by nginx because it doesn't need anything else.
I still have a Redis instance that was deployed once, so it doesn't bother me much.&lt;/p&gt;
&lt;p&gt;The last thing I'd like to share is how I handle multiple versions of the game.
It's not very useful right now since we don't have many players but it felt like something I had to do correctly from the start because it would be harder to add later on.
Since the game can change from one version to another (because we had features), incompatibilities can arise: the frontend can send a request in an older format or the API can require new information the frontend cannot send yet.
The result would be a broken game for the player.
I could use feature flags to detect which code path to use and have a single instance of the API but I think it would clutter the code more than serving the actual purpose.
So I decided that each version of the frontend would talk to a dedicated version of the backend.
To do that, I developed a small gateway which reads the version of the API the frontend wants and transfer the traffic to the proper container.
It's written in Go because I really wanted to give another try to this language and though this routing gateway would be a very good fit for the language (which I still think it is).
When you go on the site, nginx will always serve the latest version of the frontend by default.
Once you start a game, the version of the frontend is used in the URL so if you refresh the page, you will get the proper version.&lt;/p&gt;
&lt;p&gt;To conclude, I really like the project.
It took time to go to where we are now for various reasons: I made mistakes because I was a beginner, I can only work on the project during my spare time, I'm mostly the only developer working on the project and we made some changes in the gameplay that had a huge impact on the structure of the project.
Overall, I am pleased and proud of the work accomplished.
I learned a lot, was able to try thing and spent countless hours over Python, JS, Bash or Docker problems.
This may sound like a loss of time but it was a great way to learn.
I still plan to work on this project and don't know where it will be in 6 years from now.
If it's still around, I'll try to publish a follow up article!&lt;/p&gt;
</content><category term="Blog"></category></entry><entry><title>Switching from Aurelia CLI to Webpack</title><link href="//www.jujens.eu/posts/en/2020/Jul/04/aurelia-wepack/" rel="alternate"></link><published>2020-07-04T00:00:00+02:00</published><updated>2020-07-04T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-07-04:/posts/en/2020/Jul/04/aurelia-wepack/</id><summary type="html">&lt;p&gt;Recently I decided to change the build system I use on my main Aurelia project. I changed in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2016/Apr/24/switch-to-webpack/"&gt;April 2016 from JSPM to Webpack&lt;/a&gt; (JSPM was really not awesome at the time, I can't say for now), again in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2016/Aug/17/switch-to-aurelia-cli/"&gt;August 2016 from Webpack to the CLI&lt;/a&gt; and now I am …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently I decided to change the build system I use on my main Aurelia project. I changed in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2016/Apr/24/switch-to-webpack/"&gt;April 2016 from JSPM to Webpack&lt;/a&gt; (JSPM was really not awesome at the time, I can't say for now), again in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2016/Aug/17/switch-to-aurelia-cli/"&gt;August 2016 from Webpack to the CLI&lt;/a&gt; and now I am switching back to webpack. At the time, I moved away from webpack because of a big bundle of 1.3 MB that was always loaded. I didn't manage to split it correctly using Webpack while Aurelia CLI gave me the flexibility I needed to load less JS by default. So why did I decided to switch again?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;To get smaller bundles: since Webpack is not used just by Aurelia it supports many optimisation to reduce the size of your bundles (like tree shaking to remove unused code).&lt;/li&gt;
&lt;li&gt;To simplify assets management: Webpack can do it directly. I used to rely on &lt;a class="reference external" href="https://www.npmjs.com/package/gulp-rev"&gt;gulp-rev&lt;/a&gt; to correctly version them. But it required manual work to get it working. Now I can just rely on Webpack.&lt;/li&gt;
&lt;li&gt;Currently, Server Side Rendering with Aurelia is only supported by Webpack. This could be a big plus for my site where I have public facing pages that would gain from being correctly indexed by Google.&lt;/li&gt;
&lt;li&gt;Hot Module Reload to speed development (alone this wouldn't have been enough for a switch, but it's nice).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since my last try, Webpack and Aurelia's support for Webpack both significantly improved so I guessed this was worth a try to help me reduce my bundles (that the main reason I tried to be honest, the other ones are more bonuses).&lt;/p&gt;
&lt;p&gt;Here's how I made the switch. I:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Copied required dependencies from a new project created with the CLI (it was of course configured to use webpack, which is now the default option for a bundler). That included of course &lt;tt class="docutils literal"&gt;webpack&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;webpack-dev-server&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Changed &lt;tt class="docutils literal"&gt;.css&lt;/tt&gt; into &lt;tt class="docutils literal"&gt;.scss&lt;/tt&gt; in HTML files so styles are correctly loaded by webpack on my &lt;tt class="docutils literal"&gt;require&lt;/tt&gt; lines.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Used &lt;tt class="docutils literal"&gt;PLATFORM.moduleName&lt;/tt&gt; where necessary. This is required to bridge Aurelia with Webpack. See &lt;a class="reference external" href="https://aurelia.io/docs/build-systems/webpack/a-basic-example#introduction"&gt;the documentation&lt;/a&gt;. This mainly implied to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Add &lt;tt class="docutils literal"&gt;PLATFORM.moduleName&lt;/tt&gt; to link moduleId to their module my route configurations.&lt;/li&gt;
&lt;li&gt;Add &lt;tt class="docutils literal"&gt;PLATFORM.moduleName&lt;/tt&gt; in plugin definition.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Updated my storage service so it uses a prefix for my keys. This was required because webpack use &lt;tt class="docutils literal"&gt;localStorage&lt;/tt&gt; to store things and I looped on all the keys which resulted in errors in my code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Updated aurelia.json to match one provided by the webpack skeleton.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Added a webpack configuration. It's based on the one from the skeleton. I had to change (to match what I do in my project):&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Where I get sources from &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;app&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;The name of the static folder from &lt;tt class="docutils literal"&gt;public&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;assets&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Where I send the static files when the app is built.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Import all my images and assets directly in JS files so Webpack would correctly copy and version them. This way, in JS I can use the imported name to point to the assets and let Webpack handle the versioning. I had a bunch of gulp tasks to do this before and it was a bit cumbersome. See &lt;a class="reference external" href="https://webpack.js.org/guides/asset-management/"&gt;this page&lt;/a&gt; and &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/arena-of-titans/-/commit/b06fca566e8257b780c11135e2f691e81ab629c8"&gt;this commit&lt;/a&gt; for more details on how to manage assets with webpack. To help me generate the import lines and the mapping objects I often needed, I relied on this small Python script:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code Python literal-block"&gt;
&lt;span class="n"&gt;files_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&amp;quot;COPY HERE THE RESULT OF ``ls -d PATH``&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;import_name_to_file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;elt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;elt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;import_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;import_name_to_file_name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;import_name&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'import &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;import_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; from &amp;quot;../../&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;elt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;quot;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;import_name_to_file_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;quot;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;,'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Added &lt;tt class="docutils literal"&gt;index.ejs&lt;/tt&gt; as a base index file for webpack and adapt it to suit my needs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Updated my jest configuration so I&amp;nbsp;could run my tests again. I even went a bit further and stopped using Aurelia CLI to use Jest CLI directly. This allowed me to have access to all the options provided by Jest more easily. To do this, aside from updating the configuration to support Webpack, I&amp;nbsp;had to make sure the environment variable &lt;tt class="docutils literal"&gt;BABEL_TARGET&lt;/tt&gt; was correctly set to &lt;tt class="docutils literal"&gt;node&lt;/tt&gt;. Without it, Babel doesn't target the proper runtime and it doesn't work. Since I already used &lt;a class="reference external" href="https://www.npmjs.com/package/nps"&gt;nps&lt;/a&gt; to launch some scripts, this wasn't an issue. I defined my tasks to run tests like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crossEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;BABEL_TARGET=node jest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;coverage&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crossEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;BABEL_TARGET=node jest --coverage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crossEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;BABEL_TARGET=node jest --watch&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/arena-of-titans/-/commit/359423faff3030ddc92d870652f8ec0af82ea9c0"&gt;this commit&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Used a webpack plugin to help me generate my ServiceWorker to preload all bundles and assets: &lt;a class="reference external" href="https://www.npmjs.com/package/serviceworker-webpack-plugin"&gt;serviceworker-webpack-plugin&lt;/a&gt;. The details are &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/arena-of-titans/-/commit/abe3c290505bd46607e2d3ff5eebf87ce076b439"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I had one big issue during the switch: &lt;tt class="docutils literal"&gt;compose&lt;/tt&gt;. I use this to dynamically select a view model to display in an element like this: &lt;tt class="docutils literal"&gt;&amp;lt;compose &lt;span class="pre"&gt;view-model=&amp;quot;./${type}&amp;quot;&lt;/span&gt; &lt;span class="pre"&gt;model.one-way=&amp;quot;popupModel&amp;quot;&amp;gt;&amp;lt;/compose&amp;gt;&lt;/span&gt;&lt;/tt&gt; (where &lt;tt class="docutils literal"&gt;type&lt;/tt&gt; is passed to my component and corresponds to JS and HTML files to load on the view (for instance if type is &lt;tt class="docutils literal"&gt;transition&lt;/tt&gt; Aurelia will load and inject the content of &lt;tt class="docutils literal"&gt;transition.js&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;transition.html&lt;/tt&gt;). Sadly, Webpack doesn't know what to do with this out of the box. Luckily, I found &lt;a class="reference external" href="https://discourse.aurelia.io/t/dynamically-loading-compose-viewmodels-using-webpack/173"&gt;a thread on the forum&lt;/a&gt; that gave the solution: declare all you need to use with &lt;tt class="docutils literal"&gt;PLATFORM.moduleName&lt;/tt&gt; in the component definition. See &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/arena-of-titans/-/commit/6d223145cfd83bffb15939b1b574d17846a949fc"&gt;this commit&lt;/a&gt; for more details (or the thread on the forum).&lt;/p&gt;
&lt;p&gt;I'd also like to point out that the configuration generated by the CLI can optimize for two major use cases:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Usage over HTTP 1.1: you get fewer but bigger bundles.&lt;/li&gt;
&lt;li&gt;Usage over HTTP 2: you get a lot of small bundles (around 50 in my case).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since my site is only compatible with modern browser and supports HTTP 2, I decided to optimize for that. One important point to know is that by default, all bundles will be loaded by the &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt; even those you won't need yet. To prevent this (and put some pages in dedicated bundles), you can specify a chunk name to &lt;tt class="docutils literal"&gt;PLATFORM.moduleName&lt;/tt&gt; like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PLATFORM.moduleName('myRouteModule',&lt;/span&gt; 'chunkName')&lt;/tt&gt;. This way, all that's required for &lt;tt class="docutils literal"&gt;myRouteModule&lt;/tt&gt; to run will only be loaded when the route becomes first active. That's a good thing to know to avoid loading to much JS from the start if your app is big. See &lt;a class="reference external" href="https://github.com/aurelia/webpack-plugin/wiki/Managing-dependencies#code-splitting"&gt;this page&lt;/a&gt; to learn more about this.&lt;/p&gt;
&lt;p&gt;Results:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Bundle sizes before webpack:&lt;ul&gt;
&lt;li&gt;Total first party JS loaded on the whole site: 1.54 MB&lt;/li&gt;
&lt;li&gt;Total first party JS on the home page: 1.02 MB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Bundle sizes with webpack:&lt;ul&gt;
&lt;li&gt;Total first party JS loaded on the whole site: 1.26 MB&lt;/li&gt;
&lt;li&gt;Total first party JS on the home page: 618 kB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that's a gain of about a 400 kB. Not bad.&lt;/p&gt;
&lt;p&gt;To conclude, I am satisfied with the switch: I reached my goal and can take advantages of webpack which is nice! I'd also like to point out that the transition went way smother that I expected: I got it working in a couple of hours and then had to spend some time with various issues (like assets management or the issue with &lt;tt class="docutils literal"&gt;compose&lt;/tt&gt;) and to tailor the build to my needs which are not standard. All in all, I think I made the switch in less than 30 hours. Not bad. If your needs are less complex than mine, it should be way less than this. I guess both Webpack and Aurelia matured a lot since the last time I made a build system switch. That's a very good thing!&lt;/p&gt;
</content><category term="Aurelia"></category><category term="JavaScript"></category><category term="Aurelia"></category><category term="Webpack"></category></entry><entry><title>Should you build a SPA?</title><link href="//www.jujens.eu/posts/en/2020/Jun/15/should-you-build-pwa/" rel="alternate"></link><published>2020-06-15T00:00:00+02:00</published><updated>2020-06-15T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-06-15:/posts/en/2020/Jun/15/should-you-build-pwa/</id><summary type="html">&lt;p&gt;This article is an update to a previous article &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Jan/12/why-you-want-make-spa/"&gt;why you want to build a SPA&lt;/a&gt; which I think was laking some nuance and precision. Reading this article is not required to read this one. I'm writing this update because SPAs are very popular and I recently though more about …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article is an update to a previous article &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Jan/12/why-you-want-make-spa/"&gt;why you want to build a SPA&lt;/a&gt; which I think was laking some nuance and precision. Reading this article is not required to read this one. I'm writing this update because SPAs are very popular and I recently though more about them and realized my previous article was missing some important points. If you see some points that are still missing after reading this article or just want to share your opinion, don't hesitate to react in the comments!&lt;/p&gt;
&lt;p&gt;Some note on the context: I am currently working professionally on a website that is not a SPA but I built big SPAs as side projects. I'd like to rely on my experience to explain the pain points I encounter with this project in the hope to convince you to consider building a SPA from scratch on you next project. I hope that with this article, whether you finally build a SPA or not will be based on relevant arguments for your team and project.&lt;/p&gt;
&lt;p&gt;Since I work on a &amp;quot;hybrid&amp;quot; project with pages being generated server side and part of the page managed by jQuery or React, I experience many pain points due to this architecture. I guess it was the main motivation why I wrote the previous article: these points wouldn't exist if we had built a SPA. I'd also like to note that most of these decisions were made before I arrived in the company. Let's review these pain points:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Interactions between jQuery or vanilla JS and React (I'll talk mostly of React here because that's what I use at work, but my examples should apply to any other &amp;quot;framework&amp;quot; &lt;a class="footnote-reference" href="#vue-react-framework-or-lib" id="id1"&gt;[1]&lt;/a&gt;). That is a very big pain point. Some actions are triggered by jQuery by interactions made on the page. The event handlers are attached by jQuery to the DOM. This is mainly done to hide and show elements on click. The problem is: React can destroy any part of the DOM at any time when re-rendering a component, thus destroying the elements you attached an event handler on, therefore breaking interactivity. Some strategies were built to prevent this: mainly to hook on component lifecycle to readd the event handlers once React added the new elements in the DOM. It is impractical and a big source of bugs. Since React can handle events for us and can show/hide elements, there is no point to use jQuery for this. Just go with strait React, the result will be more simple and you will avoid lots of bugs that are hard to find and fix. Luckily, this practice died in our project, but I still insist on it because it was such a pain and I guess we aren't (weren't?) the only ones doing this.&lt;/li&gt;
&lt;li&gt;Big DOM manipulations in plain JS or jQuery. I don't really know why it's this way since we have React for some pages but sometimes we just create lots of HTML elements with jQuery to avoid a full reload of the page or to hide and display form elements based on very complex business rules. These pages don't even load React, all is done with jQuery. The code is bad and hiding/displaying elements based on events is a source of bugs. I guess it was made this way because it was perceive as easier and quicker. What's sad is that from what I understand the price for React was already paid when these pages were built:&lt;ul&gt;
&lt;li&gt;We already had pages (part of pages to be exact) in React so it's there and available (and a better fit for these problems).&lt;/li&gt;
&lt;li&gt;The build system was configured and could load only small bundles of JavaScript.&lt;/li&gt;
&lt;li&gt;Team members had to learn React at this point and from my perspective it makes sense to pay the investment where/when it makes sense. In the long run, it will allow us to go faster with less bugs.&lt;/li&gt;
&lt;li&gt;The code is hard to understand and buggy.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;On some pages we do the initial render with Django and then React kicks in to re-render the page and add interaction. This feels like duplicated work that can be optimized.&lt;/li&gt;
&lt;li&gt;Interactions between different part of the page can be hard: we can have several small React apps on a page and sometime they must communicate or share common data (for instance: whether the user is logged in or not). Since they are independent and not part of a bigger app, communications is harder than it could be.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The question now is: is this enough to build a SPA? The ecosystem is now mature enough so we can have a way to create and reuse components, very good support for templating, updating components if some data changes and routing with any framework. By routing I mean that the URL in the URL will be updated as if it were rendered on the server (and not just a hash change) with history and back/forward buttons working as expected. Now we can also have Server Side Rendering (or SSR for short) to pre-render our app on the server and thus speed up initial page load as well as making our app easy to index by crawler. This will avoid us any SEO impact. So, it looks like everything would be better in the wonderful world of SPAs, but is it?&lt;/p&gt;
&lt;div class="section" id="why-wouldn-t-we-build-a-spa"&gt;
&lt;h2&gt;Why wouldn't we build a SPA?&lt;/h2&gt;
&lt;p&gt;Maybe instead of thinking at why we want to make a SPA, we can start by looking at why we wouldn't want to build one (the points below are not really in importance order):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Habit or never built a SPA before. That's the weakest argument since SPA can definitely be a good thing. My advise would be: learn about SPAs and their advantages and downsides, learn how to build one and then try to build one in a test project to see how it goes. You will then have better insights on whether a SPA would be a good fit for your project.&lt;/li&gt;
&lt;li&gt;Lack of skills: a much better argument, in my opinion. Building a SPA requires much more JS and frontend skills than building what I'll call a &amp;quot;standard&amp;quot; or &amp;quot;normal&amp;quot; site. But if you avoid building a mess with jQuery, it will be easier for you to hire developers with the right skill set (I don't think they'll join you to maintain the jQuery mess) and to maintain and add feature to it in the long term. And these skills can be learned: from my experience, modern JS and its frameworks can be learned (more or less rapidly depending on which framework you choose and your experience with JS and they'll of course come with their own set of quirks). But it's definitely doable. If you team is lacking UX or design skill, try to rely a contractor to help you, since (from my perspective) those skills will be harder to learn for developers.&lt;/li&gt;
&lt;li&gt;SPA are complex to build and also require a mindset changes from how we do things in the backend. That's true, and if you are not used to building them, depending on the application your are building it may not be worth the trouble. So keep reading to learn more!&lt;/li&gt;
&lt;li&gt;SPAs hurt SEO: since the server will respond with a HTML file without content, crawlers can't parse anything interesting from the page. It's a valid concern that can be mitigated with Server Side Rendering (SSR) or pre-rendering. Read the sections about this below if you want to know more.&lt;/li&gt;
&lt;li&gt;Slow initial page load: same as above, the browser needs to load and parse JS before displaying anything. It may even require some extra HTTP requests to get required data before displaying anything. This can also be mitigated by SSR or pre-rendering, see below.&lt;/li&gt;
&lt;li&gt;Extra work: you must re-implement things that comes for free in the browser like a loading icon or error handling. Frameworks or libraries can help, but it sure is extra work.&lt;/li&gt;
&lt;li&gt;Bundle size: the browser will need to load more JS which can be an issue on low end devices (like some phones) or on poor connections (mostly on phones too). Depending on who you are targeting this may be a big issue. This can be mitigated by the fact that you can load only part of the JS on each page. Don't forget that marketing typically also includes lots of JS because of various trackers and advertisers. So &amp;quot;your&amp;quot; JS may not be that big (or big enough to be an actual issue) compared to all the other things you have to load (but it is more important for the page to render).&lt;/li&gt;
&lt;li&gt;Memory leaks: since your user will stay a very long time in you app, if you don't pay attention, some objects may never be garbage collected resulting in poor performance and high memory usage. But normally, if you follow the best practices of JS and your framework this shouldn't be an issues (like clearing timeouts and interval, unsubscribing to store events…).&lt;/li&gt;
&lt;li&gt;Security: how do you authenticate? How do you protect against XSS and CSRF? Those are hard questions and I think we find many misleading information on the internet. I'm no expert and encourage you to do your own research on this (it's also way outside the scope of this article). I'll just write some notes based on mine:&lt;ul&gt;
&lt;li&gt;You can still use cookies with SPA: if your app and your API are on the same domain, even an AJAX request can set a cookie easily. If you do use cookies, make sure they are HTTP only (so JS can't access them to prevent attackers to steal authentication information with XSS), secure (so they are only transmitted over HTTPS). You should use CSRF tokens and probably also use the Same Site header (to prevent sending to cookie to your site when your user are on another site) to prevent CSRF attacks. I think that even if they are not the most trendy choice any more, cookies are a very good mean of authentication which is secure and robust and whose problems are well known with ways to prevent those that exist. This is not always the case for other means of identification.&lt;/li&gt;
&lt;li&gt;Enable CSP (Content Security Policy). This will allow you to choose what your browser can do. For instance, it can be used to disallow execution of inline JS to prevent XSS attacks.&lt;/li&gt;
&lt;li&gt;If you use tokens (with JWT for instance), beware of how and where you store them. See &lt;a class="reference external" href="https://www.rdegges.com/2018/please-stop-using-local-storage/"&gt;this article&lt;/a&gt; for more details on this.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;User experience: it can be harder to achieve a good UX because we need to correctly re-implement things that our browser handles natively. And we can do it poorly. I'm thinking of GitHub here: once you loaded a page, you will navigate without a full page reload. Sometimes, it's slow and I seem stuck on a page and just by pressing F5, I can reach the page I'm trying to access immediately (you probably experienced this too). So I guess even for very good tech teams this can be hard.&lt;/li&gt;
&lt;li&gt;The technology is still evolving fast, how can we know it will stick around? A fair and complex question. If the list big names seems to have stabilized, the frameworks themselves are still evolving. I think the &amp;quot;big ones&amp;quot; (React, Vue.js, Angular…) will stick for a while because of the sheer number of projects using them. Let's also be honest: what says your backend tech will stay around or won't add breaking changes? It's used widely now but it can be replaced by something else (by a new shiny thing on &lt;a class="reference external" href="https://deno.land/"&gt;Deno&lt;/a&gt;?).&lt;/li&gt;
&lt;li&gt;Overload the backend with too many requests: I guess it can happen if your app need to do a bazillion requests on each page. But I think it's more a design issue than a problem with SPA: why is it doing so many requests? Can we group some? Can tools like &lt;a class="reference external" href="https://graphql.org/"&gt;GraphQL&lt;/a&gt; help?&lt;/li&gt;
&lt;li&gt;Reinventing the wheel: For example you will need to find a way to restore the scroll position by any page change, add extra loaders to show that the contents are not yet ready, keep the page &lt;tt class="docutils literal"&gt;&amp;lt;title&amp;gt;&lt;/tt&gt; in sync with your content and much more… It's free in the browser and it can take time to do all of these little features correctly.&lt;/li&gt;
&lt;li&gt;Improper status code: I don't mean error handling of an AJAX requests that failed, I mean that your server must always answer something and, a priori, cannot know whether a route exist. So it will always respond with 200 and the index file. This can be mitigated with SSR, see below.&lt;/li&gt;
&lt;li&gt;Accessibility: you can have issues but it's definitely getting better and your classic sites may lack important accessibility features too, let's be honest here. I think it's more whether you will take the time to add these features to your site than a problem with the tools themselves. See &lt;a class="reference external" href="https://www.deque.com/blog/debunking-the-myth-accessibility-and-react/"&gt;this article&lt;/a&gt; for more.&lt;/li&gt;
&lt;li&gt;Your application requirements don't need it. That's a traitorous argument I think because the requirements can evolve and you may end up needing much more interactivity than you initially though. In the end, it will highly depend on the project you're building and your trust in the requirements to continue not to need a lot of JS. Here are some:&lt;ul&gt;
&lt;li&gt;Your app is read only.&lt;/li&gt;
&lt;li&gt;Your are just dealing with basic forms, where HTML5 validation (or just a bit of JS validation) will be enough.&lt;/li&gt;
&lt;li&gt;Your app must work without JS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="ssr"&gt;
&lt;h3&gt;SSR&lt;/h3&gt;
&lt;p&gt;Since SSR is trendy and can help mitigate some of the most blocking issues with SPA (namely initial load and SEO), here are a few notes SSR.&lt;/p&gt;
&lt;p&gt;What is it and how does it work? As I said in the introduction, the point of SSR is to pre-render your app on the server.&lt;/p&gt;
&lt;p&gt;Without it, when you request the first page of your SPA, the server will respond with a HTML file that only contains links to JavaScript files. It cannot display anything directly, it has to load the JS and execute it so your JS code can render the content of the page. During this rendering phase, your browser may need to do extra requests to get extra data. The following pages will be handled by the routing module of your SPA and won't require a page reload, but they still can require additional network requests to get the content of the page. The communication between your app and the server is typically done using the REST conventions with JSON as the exchange format (although, now, GraphQL is gaining popularity).&lt;/p&gt;
&lt;p&gt;If you enable SSR, your app will first run on the server thanks to NodeJS. Since the server ran the app, it can supply the browser with a complete HTML file that is ready for display. This means the page will display faster in the browser of the user, it will work correctly with search engines and environments that don't support JS. You should also be able to make the server correctly respond 404 for pages that don't exist (which is not easy to do normally since the app written in JS knows whether the route exists or not, the server that serves the base HTML file doesn't).&lt;/p&gt;
&lt;p&gt;It comes at a cost though:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Your app must be able to run in NodeJS. Depending on your host provider, architecture…, it may not be possible. One thing is sure, your architecture will be more complex if you go this way.&lt;/li&gt;
&lt;li&gt;Your application must be designed to run in the browser and in NodeJS (code that can do that is said to be isomorphic). But you cannot code as if you were only supporting the browser. For instance, you cannot access the DOM directly since it doesn't exist on Node, you must go through an abstraction which should be provided by your framework. I think making your app run correctly in the two environments will be one of the most challenging part when doing SSR.&lt;/li&gt;
&lt;li&gt;If your app takes time to start after the HTML is sent to the user, you will have to capture events (like button clicks) to replay them once your app has started. And if it takes really too long, I think you defeated the point of SSR and displaying fast an usable app to your users is worse than starting with a spinner that at least indicates the app is loading.&lt;/li&gt;
&lt;li&gt;Since the code will be run many times on the server, you need to pay attention to:&lt;ul&gt;
&lt;li&gt;Not use &lt;tt class="docutils literal"&gt;setTimeout&lt;/tt&gt; since it can block rendering until the timeout has expired or use &lt;tt class="docutils literal"&gt;setInterval&lt;/tt&gt; because intervals may pile on causing memory and performance issues (this can be mitigated if you don't forget to clean them correctly).&lt;/li&gt;
&lt;li&gt;Don't update prototype of global objects.&lt;/li&gt;
&lt;li&gt;Call required cleanup functions (like &lt;tt class="docutils literal"&gt;unbind&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;detach&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;unsubscribe&lt;/tt&gt; in Aurelia) to clean the memory of the process and make sure page renders don't leak memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The response time can increase if the server is busy and it will be harder to support high loads: without SSR, most of the work is done on the client side, the server that serves the app only has to supply static files, so the server will handle high loads better. If you have many or big API calls to populate the content of the page, it may be a problem in both cases though. But keep in mind it's another potential bottle neck.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So depending on what you do and what your stack is, it may not be possible, very hard or not worth the cost. But if you can do it, it can be a huge plus to avoid major pain points. Small disclaimer to conclude with this section: although SSR looks mature for all the major frameworks I have never used it in production yet, so I have no idea of what other issues you can encounter if you go down this path (I did test it though).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pre-render"&gt;
&lt;h3&gt;Pre-render&lt;/h3&gt;
&lt;p&gt;One alternative to SSR, is pre-rendering. It's almost the same except instead of rendering the page when we ask it, we pre-renders all the public pages of the website, save the result and serve the result directly when requested. So it should be faster and reduce server load since we mostly server static files on the first request.&lt;/p&gt;
&lt;p&gt;I haven't tested this, but I can guess that if it is done properly, when you app boots, you can override part of it (let's say to display a username) just like you would have with a normal site. It may flicker a bit while you update the pre-rendered version though (but again, just like on a normal site). I also guess you can make sure only anonymous users get the pre-rendered pages to avoid this altogether.&lt;/p&gt;
&lt;p&gt;I'll also note that this technique can work with SSR: you rely on SSR to pre-render your website and you then send this pages to your users.&lt;/p&gt;
&lt;p&gt;There are also services that allow you to do just that like &lt;a class="reference external" href="https://prerender.io/"&gt;prerender&lt;/a&gt; (which also has an OpenSource version), &lt;a class="reference external" href="http://www.brombone.com/"&gt;bromdone&lt;/a&gt;, &lt;a class="reference external" href="http://getseojs.com/"&gt;getseojs&lt;/a&gt; or &lt;a class="reference external" href="http://www.seo4ajax.com/"&gt;seo4ajax&lt;/a&gt; (and probably many more). Even if they are paid services, it would reduce the complexity of your infrastructure since you won't have to maintain servers for that. From what I understand, all these services work more or less the same way: they launch a headless browser to render your pages and save the results so they can serve them later (which mean you don't have to support SSR to use them). When a request is made to your server, you choose whether the response should come from the pre-render service or not. Meaning that for your users, the content will always come from your servers and domains. If the content served by the service is close enough of the content without it, google won't consider it like &lt;a class="reference external" href="https://support.google.com/webmasters/answer/66355?hl=en"&gt;cloacking&lt;/a&gt; and penalize your SEO (both content should be the same anyway). Google even &lt;a class="reference external" href="https://developers.google.com/search/docs/guides/dynamic-rendering"&gt;recommends this technique&lt;/a&gt; &lt;em&gt;if your site uses technologies that search engines have difficulty accessing, like JavaScript, images, or Flash&lt;/em&gt; (to quote their page about cloaking linked before).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="so-when-would-we"&gt;
&lt;h2&gt;So when would we?&lt;/h2&gt;
&lt;p&gt;Now that we've discussed in detail when not to build a SPA while giving nuance to each counter arguments to correctly understand whether or why it is valid, let's review some arguments in favor of building one (yes that's way shorter, but it doesn't mean the advantages aren't worth it):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Your app needs a complex and interactive user interface or state that must be persisted across many pages. The result will be way more simple in the end if you build a SPA than some kind of hybrid stuff with a static page that will need to interact with JS. That's the main reason why you would build a SPA and still accept the drawbacks of this method.&lt;/li&gt;
&lt;li&gt;Your team is already so familiar with JS and SPA (and eventually SSR), that you know in the end it will just be quicker this way.&lt;/li&gt;
&lt;li&gt;You must expose a public API. You can then reuse it directly in your SPA avoiding duplicating some work to get the data on the site.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'd also like to point out:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Your life will be easier if you can update framework and build tools frequently and if you use supported tooling (like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;create-react-app&lt;/span&gt;&lt;/tt&gt;). They evolve fast and bring enhancement frequently.&lt;/li&gt;
&lt;li&gt;Building a SPA is not required for a PWA. See for instance &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Feb/29/django-pwa/"&gt;my article about PWA and Django&lt;/a&gt; where I transform a normal Django site into a PWA.&lt;/li&gt;
&lt;li&gt;You should uniformize conventions. This can be a function that convert snake case into camel case (and reciprocally) so you don't have a mixed conventions in your frontend (or in both your frontend and your backend).&lt;/li&gt;
&lt;li&gt;You can still handle style with CSS (or SCSS) files, you don't have to go down the CSS in JS road.&lt;/li&gt;
&lt;li&gt;SPA can handle translations and internationalization. The framework you choose should have libraries to help you do that.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="how-about-hybrid"&gt;
&lt;h2&gt;How about hybrid?&lt;/h2&gt;
&lt;p&gt;You may already have a website and need to add interactivity to it. Should you rewrite everything? Probably not, it would take a lot of time and your site already works. If your pages are private and don't require SEO, maybe you can convert some pages to &amp;quot;SPA&amp;quot; (you won't get an app, just a page but it will be close of a SPA for the principles used).&lt;/p&gt;
&lt;p&gt;If not, you can include interactivity to part of a page to build what I'll call an hybrid app. This is typically done with React or Vue.js because they have a much smaller footprint than the other frameworks. This is because they do less things and are only concerned with rendering. It also means you may need more extra libraries to do what you want than with frameworks like Angular or Aurelia.&lt;/p&gt;
&lt;p&gt;Will the result be a monstrosity like most hybrids in fiction? Not necessarily. Here are some tips that can help you:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Use CSS and vanilla JS if you can since this will be less complex. Just keep in mind this will only work for the most basic cases.&lt;/li&gt;
&lt;li&gt;For more advanced cases, you will need a framework like React or Vue.js. One important thing to remember, is to always use the framework for rendering and handling events: it can react to all events you'll need (click, form submit, hover…) and conditional hide/display something. Don't interfere with it, if you do, you will run into trouble and hard to correct bugs (as I pointed out earlier). Once you are in the framework, you use the framework.&lt;/li&gt;
&lt;li&gt;You can pre-render the content of the app in your backend with your backend templating language if you don't wish to display a spinner or if you wish to display content faster or to support SEO. Just make sure the app loads fast so everything works when your users try to interact with the page. Also note you will have to duplicate the display and probably part of the logic in the backend templates. Make sure it's worth it.&lt;/li&gt;
&lt;li&gt;Use JSON for communication with your backend if you can. It will be easier to read and debug when a problem arises.&lt;/li&gt;
&lt;li&gt;Display a loader and handle errors (eg display a message to the user) when things go wrong as you would in a SPA.&lt;/li&gt;
&lt;li&gt;Rely on your backend for security: don't try to use tokens, just go with cookies and session authentication just as you would if your were building a &amp;quot;classic&amp;quot; site. Don't disable CSRF protection!&lt;/li&gt;
&lt;li&gt;If many small independent JS applications need to communicate on the same page, you can create a global store to allow them to share the same source of data and interact with each other.&lt;/li&gt;
&lt;li&gt;If you are in this situation, your team is probably mostly backend or full stack developers. Don't hesitate to train them so they are efficient with the frontend tech you choose and to rely on a designer for design and UX.&lt;/li&gt;
&lt;li&gt;By all means, avoid jQuery in the JS apps. As I said earlier this can lead to issues when interacting with the framework.&lt;/li&gt;
&lt;li&gt;Please don't build a hybrid with jQuery, it's awful to work with and thus can hurt hiring and developers retention. jQuery can still be used if your needs for interactivity are low, in my opinion, but be ready to move away from it if your needs grow bigger and to rewrite part of your app.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are starting a new project and intend to build a hybrid instead of a SPA (or a classical site), please:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Think again, you may need more interactivity than you initially though and a SPA may make things easier and more simple in the long run despite a slower start.&lt;/li&gt;
&lt;li&gt;Pay attention to the skills in your team and train/prototype if needed.&lt;/li&gt;
&lt;li&gt;Don't underestimate the work of maintaining two templates if you need SEO (and don't go for CSS in JS since you will need to duplicate the style in CSS for your main templates to render correctly). This of course only apply if you don't use pre-rendering.&lt;/li&gt;
&lt;li&gt;SSR can be harder to achieve: depending on your stack, you may need to launch another process from your main web process to execute the JavaScript. This may not be possible nor desirable. Pre-rendering should work exactly like with a SPA though, making it a very good solution.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="wrapping-up"&gt;
&lt;h2&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;To conclude:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Whether to build a SPA highly depends on your team and requirements. There is no general answer.&lt;/li&gt;
&lt;li&gt;Please don't make a SPA only because it's popular or that's what trendy startup or big companies like Facebook or Google do. This can turn out to be a disaster for you. Make sure to understand the tradeoffs involved.&lt;/li&gt;
&lt;li&gt;On many occasions, a static website (ie a site only made of static pages that can be served directly by a web server) like this blog can be the best option. There are many generators out there to help you build one with plain HTML file or markup format like markdown. &lt;a class="reference external" href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt;, &lt;a class="reference external" href="https://docs.getpelican.com/en/stable/"&gt;Pelican&lt;/a&gt; and &lt;a class="reference external" href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; are popular solutions for this.&lt;/li&gt;
&lt;li&gt;Don't use jQuery for complex use cases, we have better solutions now (mostly if you want to do big DOM manipulations).&lt;/li&gt;
&lt;li&gt;Don't try to make jQuery (or vanilla JS) interact with the framework. Rely on the framework all the way!&lt;/li&gt;
&lt;li&gt;Keep in mind that simple is different than easy: something hard now can turn out to be simple in the long term. So learning how to do SPAs and building one, although harder at first may be the right option in the long term.&lt;/li&gt;
&lt;li&gt;Whatever you do now, learn frontend dev (or backend dev if your are a frontend person), you will need these skills to at least help make the best decisions (like choosing when to do a SPA) and to interact with the other side of the spectrum.&lt;/li&gt;
&lt;li&gt;You probably will need more JS and interactions than you initially think.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To give a small conclusion about the project I work on: all in all, the fact that it's not a SPA is not a big deal. I have issues with some pages true, and I think we should use React more in some cases and rewrite some pages in React. But I still value Django and its ecosystem for the type of site I'm currently building. I think it gave us ease and speed to develop the site. So I think for us, a hybrid is a good choice: it gives us the possibility to add JS interactions where we need while preserving SEO. I just wished we went for React on some pages that requires lots of interactivity instead of jQuery. Since we don't need much interaction on most pages, all in all this works well. And we do have a SPA for some back office stuff where it makes sense.&lt;/p&gt;
&lt;p&gt;If you have a remark, a question or just disagree, please leave a comment below.&lt;/p&gt;
&lt;div class="section" id="small-frameworks-list"&gt;
&lt;h3&gt;Small frameworks list&lt;/h3&gt;
&lt;p&gt;Here's a small list of frameworks (at time of writing in June 2020) that you may want to look into to build a SPA:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://reactjs.org"&gt;ReactJS&lt;/a&gt;: Most likely the most popular choice right now. While it was initially design to be included in a &amp;quot;static&amp;quot; page to add some dynamism to it, you can build full SPAs with it and even mobile apps. React itself is quite small so you will probably need to add some other libraries to extend its capabilities a bit. React can be added incrementally to you site to add dynamic parts step by step.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt;: Another very popular option. Very similar to React in principles (small, incremental) with a different approach that you may prefer coming from a &amp;quot;traditional web development&amp;quot; background.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://angular.io/"&gt;Angular&lt;/a&gt;: While the first two are relatively small and can be added incrementally, Angular is a big framework designed to build full SPAs. I don't think you will be able to easily enhance an existing static website with it. While its size may be daunting, it is complete and you probably won't need much additional libraries with it. Furthermore, its tooling is mature and able to reduce the size of your code to only include the code you actually use to keep the JS you send small. Given its approach and use of TypeScript, it might be the right choice for you if you come from the Java or .NET world.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://aurelia.io/"&gt;Aurelia&lt;/a&gt;: Not as popular as the other options, but I&amp;nbsp;think it is a sweet spot between the completeness and complexity of Angular and minimalism of React or Vue. Like Angular it is a complete framework designed to build SPAs, but it has a good focus on web standards and tries to get out of your way so you can write standard JavaScript or include standard JavaScript libraries as easily as possible. Which makes it easier to learn and develop with (in my opinion at least). It's my go to choice for my personal projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="resources"&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;p&gt;Some interesting resources I read to help me improve my opinion on SPAs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.scalablepath.com/blog/single-page-applications/"&gt;https://www.scalablepath.com/blog/single-page-applications/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://blog.usejournal.com/spa-or-not-spa-that-is-the-question-711ace3576cf"&gt;https://blog.usejournal.com/spa-or-not-spa-that-is-the-question-711ace3576cf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/choose-between-traditional-web-and-single-page-apps"&gt;https://docs.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/choose-between-traditional-web-and-single-page-apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.freecodecamp.org/news/server-side-rendering-your-react-app-in-three-simple-steps-7a82b95db82e/"&gt;https://www.freecodecamp.org/news/server-side-rendering-your-react-app-in-three-simple-steps-7a82b95db82e/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://aurelia.io/docs/ssr/introduction/"&gt;https://aurelia.io/docs/ssr/introduction/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table class="docutils footnote" frame="void" id="vue-react-framework-or-lib" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;You may say React and Vue are more libraries than frameworks. I agree, but I'll keep calling them frameworks to ease writing since I also want to include SPA frameworks like Angular or Aurelia.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category><category term="Web"></category><category term="Django"></category></entry><entry><title>JavaScript fatigue</title><link href="//www.jujens.eu/posts/en/2020/May/31/javascript-fatigue/" rel="alternate"></link><published>2020-05-31T00:00:00+02:00</published><updated>2020-05-31T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-05-31:/posts/en/2020/May/31/javascript-fatigue/</id><summary type="html">&lt;p&gt;Today, I'd like to dig into something that has been bothering me lately: why I often feel tired of JavaScript (and even sometimes programming in general). I'm not alone in this, there's even a name for this &lt;em&gt;JavaScript fatigue&lt;/em&gt;. Here I'll give my personal thoughts on this (and probably rant …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today, I'd like to dig into something that has been bothering me lately: why I often feel tired of JavaScript (and even sometimes programming in general). I'm not alone in this, there's even a name for this &lt;em&gt;JavaScript fatigue&lt;/em&gt;. Here I'll give my personal thoughts on this (and probably rant a bit).&lt;/p&gt;
&lt;p&gt;As developers, we do live in a fast moving world. It's even more true in the world of frontend development and JavaScript: it seems a new framework or practice appears every day and everything seems to force us to know about it and to learn it because it is so new and so cool and so much better than everything else that came before it.&lt;/p&gt;
&lt;p&gt;This doesn't come from nowhere: with the rise of NodeJS and interactive apps, JavaScript is more and more used and so its community is expanding. Fast, very fast. This means the number of developers using the language, contributing to it and its ecosystem is increasing too. Quickly, very quickly because of the need for these skills and the &amp;quot;hype effect&amp;quot;.&lt;/p&gt;
&lt;p&gt;Add to that the fact that not so long ago (before Chrome and V8 and the evolution ES2015/ES6 of the language), JavaScript was still lacking what I'd call &amp;quot;important features to be productive&amp;quot; and was seen more as a side language to add some interactions in the browser. So there were some frameworks but nothing that got a real big momentum and pretty much everything still had to be built. This means, in this space, we are all using recent tech. This is quite unlike what we had (and still have) in the Python world for instance with frameworks like Django (first released in 2005) or Flask (first released in 2010) or in the Ruby world with Ruby on Rails (first released in 2005). Even if nodeJS itself was release in 2009, it takes time for an ecosystem to raise and mature with all of its libraries and frameworks and then for developers to adopt it (beyond the early adopters of course). In the frontend side of things, I think it really started with AngularJS in 2009 which was the first attempt (that I know of at least and that really became popular) for a framework to allow you to build a true SPA that became really popular. It was then followed by React in 2013, Vue.js in 2014, Angular in 2016 and Aurelia in 2016 to name only the most known. They are of course many others, most of them will probably remain experiments.&lt;/p&gt;
&lt;p&gt;You can object that some of the projects I listed earlier are more or less as recent as the JS ones, after all both AngularJS and NodeJS were first released in 2009. However, they have share an important difference: they were built on concepts and rely on technologies that are much older, mainly:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The MVC model which dates from 1978.&lt;/li&gt;
&lt;li&gt;SQL which dates from 1974. Of course both PostgreSQL and MySQL are more recent: 1996 with sources in the INGRES project way back in the 70s and 1995 respectively. But since they are at least 25 years old, they are kind of venerable now.&lt;/li&gt;
&lt;li&gt;Python or Ruby which date from 1991 and 1995 respectively.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And even if the projects can be new, they are based on &amp;quot;old&amp;quot; tech and concepts that matured before these projects came to be. And they are more or less 10 years older than most framework we use today in the frontend. These concepts evolved and were refined over time which took time. We were able to test many possibilities, to fail, to learn before getting where we are now: mature stuff that works in many cases and are stable.&lt;/p&gt;
&lt;p&gt;Contrast this with Express.js which was 1st released the year after Node was or the NoSQL movement which really starts near 2009 (MongoDB was release this year and the first NoSQL convention happened), like NodeJS and AngularJS. Or JavaScript itself which added &amp;quot;basic&amp;quot; feature only recently (like the import system in 2015). You can of course argue the root of NoSQL is older but my point is it gained momentum and was formalized very recently (at least in the form we know and use).&lt;/p&gt;
&lt;p&gt;So, I feel we are still missing maturity for frontend tech. The technologies are all recent, evolving fast and don't seem close to a stabilization (I hope this will change in the future). The fact that there is so many developers using it and wanting to bring their ideas to it doesn't help either.&lt;/p&gt;
&lt;p&gt;Which leads to the situation I was describing in introduction: we see a lot of experimentation, technologies move fast, become deprecated quickly and we have a lot to learn just to stay up to date. This can lead to a feeling of exhaustion because no matter what we do, even if we try to only stay relevant, we still feel out of date without any clue to what we should learn, what would be most valuable, what will last. That applies to tech that have been around for some time like React: they recently introduced hooks which are a brand new and very different from what we did until then to manage state. And we are expected to by peer pressure (on social media or internally where we work) and to pass interviews (mostly at the latest trendy startup but that where the cool kids go, isn't?). And if like me you like learning things and experimenting, this can be daunting and exhausting.&lt;/p&gt;
&lt;p&gt;Of course, they are things we can do to mitigate this:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Only take a close look at tech that is popular and that passed the trial of time. This way, we only look at tech that had time to mature. But it can already be perceived as obsolete and it can still be evolving (I'm thinking of React Hooks that were introduced recently).&lt;/li&gt;
&lt;li&gt;If we want to look at some latest stuff to have fun, we can, just do it only once or twice per year and don't dive all in since we probably won't use it anyway (or it will just disappear). And remember that we are learning it for fun not to use it in production.&lt;/li&gt;
&lt;li&gt;Reduce our usage social media where we can be submerged by the hype wave and where it looks like everybody gives their opinion even if they haven't though on the matter and where people can be quite enthusiastic about anything, making ou feel bad your are not and giving us the false impression the thing we are looking at is very popular and that we just must use it (and that everybody already is). The problem is also similar at conferences but I can't really advise not to go at one or watch their recorded videos because they are a magnificent way to learn. And they have a big difference: when you go to a conference, you can talk to people to get a more nuance picture.&lt;/li&gt;
&lt;li&gt;Remember about cognitive bias: speakers are most likely normal folk too and many of them are just average. That's just statistics. Speaking at a conference doesn't make them heroes we must follow no matter what.&lt;/li&gt;
&lt;li&gt;Remember even those cool folks have to maintain legacy code and don't always do the cool stuff they talk about. But that's easier said than done. And, like most of us, they'll talk about the cool stuff they are doing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's good and that can help. It can still be hard to do, if like me, you like to experiment and learn new things. Since as developers we all work with our brain and are attracted to technology, I think it's the case for many of us.&lt;/p&gt;
&lt;p&gt;But it's only part of the solution and making it only rely on people, on us personally, can make us feel bad and worsen the problem. Even if that's what our culture incite us to do. I want to emphasize that it's also a global context. And the big pression to follow the hype will still be there and each time we'll go to a meetup or a conference. It's also present in how we make job interviews. And if we don't work in a big company or a startup where we can test, experiment and work the latest stuff during work hours, it's even harder because we must do it all on our valuable spare time. So I feel like we need to collectively do something and stop chasing the brand new thing, for us and for others. Here is a small list of things we can do:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Stop reinventing the wheel because we didn't to it or because we think we could do it a bit better.&lt;/li&gt;
&lt;li&gt;Stop blaming and criticizing the old tech and the users of old tech:&lt;ul&gt;
&lt;li&gt;The tech may be old but it doesn't meant it's irrelevant. We can even learn things from it and become better developers (and dare I say like it?).&lt;/li&gt;
&lt;li&gt;It's maybe a much better match for what they are doing than the shiny stuff (whose main quality is often to be new and shiny).&lt;/li&gt;
&lt;li&gt;The user of old tech may just not be following the hype and be convinced for very good reasons that the tech they use is good for their problem. Even if it has some defects and it's not prefect, the issues and imperfections are known and very often can be dealt with. They know how to be productive with it and keep the software going with few bugs.&lt;/li&gt;
&lt;li&gt;They may also not have a choice and have to maintain a big legacy project.&lt;/li&gt;
&lt;li&gt;There is a place for proven tech even outside legacy systems.&lt;/li&gt;
&lt;li&gt;Please note that I'm not advising never to learn, experiment or move forward. Don't get stuck into your habits: think about them and make them evolve when needed. Don't choose an old tech because you're used to it but because you know it is good. New tech can spawn great values. This implies to read books and experiment from time to time. It just doesn't need to happen at a fast pace and for everything that happens out there. Focus on the basis and high level architecture, it can be reused across languages and tech so it always pays off.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Accept we are no all working at Google, Facebook or any other very big player. We don't need to work exactly like they do, with their tech and their procedures.&lt;ul&gt;
&lt;li&gt;We will probably be more productive if we don't. Most of what they do is design for the enormous load they have and for the huge number of developers that work for them.&lt;/li&gt;
&lt;li&gt;Even in a startup with big ambitions, we are likely to miss something that will prevent your architecture to scale correctly and force you to rewrite it. Even if the software was written with all the latest shiny tech and separated in µ-services. And let's face it, the startup is very likely to disappear anyway. So maybe we should try to build a product that works and get customers before thinking about scaling at the level of Google.&lt;/li&gt;
&lt;li&gt;We will probably apply the visible stuff without all the technical rigour that comes into it. This will result in us building a big mess of little balls of mud that will shine it meetups but prevents us to deliver.&lt;/li&gt;
&lt;li&gt;So maybe try to build a good product following proven code advise (like those described in the book &lt;em&gt;Clean Code&lt;/em&gt;) and it will be easier to you to pivot or scale should it be needed. And if we have to rewrite it, do it. If our software was done properly, it will take time, but it will be doable (normally at least, we all hope and we all fear the tech debt ^^).&lt;/li&gt;
&lt;li&gt;Old stuff is always a pain to maintain anyway, whether written in a shiny new µ-service architecture or in a big monolith.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Accept that the hype is the hype and probably isn't mature enough to be used in the real world just yet for most companies.&lt;ul&gt;
&lt;li&gt;Most of us can't afford to rewrite everything each time something new – a framework or a version of a framework – comes along. Don't blame anyone for not being into it. They may have other priorities and they don't have the resources (the army of developers and the billions of dollars) to make it happen anyway.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Find a job that allows you to learn and stay relevant during work hours to better enjoy your spare time.&lt;/li&gt;
&lt;li&gt;Accept that old tech with known tradeoffs can be a good thing.&lt;/li&gt;
&lt;li&gt;Don't forget that most of the common problems with &amp;quot;old&amp;quot; can be mitigated because we understand the tech so well with decades of experience with it.&lt;/li&gt;
&lt;li&gt;Don't forget old tech evolves. For instance recent versions PostgreSQL has astonishing support for JSON and can help you apply schema migrations without downtime. So bringing this as a hammer argument for MongoDB may not be relevant.&lt;/li&gt;
&lt;li&gt;Don't forget some issues with old tech comes for a particular framework, lib, or software. For instance, PostgreSQL supports array and has for a very long time unlike MySQL (which as far as I know still doesn't). Arrays are even in the SQL standard, so criticizing SQL for this is in fact criticizing MySQL. Take care of this. And they too can evolve and provide those features, so you may not need change them.&lt;/li&gt;
&lt;li&gt;We need time to understand the tradeoffs of new tech. Embracing it too early can lead to bigger problems in the long run that using old and proven tech. It is cool that some can do it and find these issues. Not everybody can do it though, and for many solutions that brings money to a company, it's not a good fit. And we may encounter problems nobody has before and nobody knows how to solve which may put us in a delicate solution.&lt;/li&gt;
&lt;li&gt;In the real word, behind the buzzword, many are probably not doing like the Big Ones and building a big ball of µ-services or fail at understanding a problem correctly even if they proudly display their state of the art practices. Even in the big ones, I sure the reality is a bit less interesting than what they present at conferences.&lt;/li&gt;
&lt;li&gt;Stop blaming people when we ask genuine questions about new tech because we don't understand their tradeoffs yet and don't fully grasp their advantages. It takes time to correctly understand a subject and build an intuition about when, how to use it and whether it's a good fit for our project and my team. Just replying with &lt;em&gt;You're just resistant to change&lt;/em&gt; is neither helpful nor mature. They can be valid reasons for a change (even proposed by Facebook) to be bad so don't use the argument of authority &lt;em&gt;It's made at Facebook or Google&lt;/em&gt;, try to convince us with good arguments instead. And don't forget the goodness of a change may not be obvious at first.&lt;/li&gt;
&lt;li&gt;Don't forget that something good for one team may not be for another. For instance, take µ-services: they are very interesting to structure big teams. If you're just 2 or 3, I think it's overkill. Or write a application in a language nobody knows in your team because you think it may be a good fit for it. But if we think about it, the advantages it brings are not that obvious. The languages you know may not be the best theoretical fit, but you know them and the ecosystem around it, which gives it a very clear advantages. So unlike it is obviously not a good choice, you should use it. Making your team to a new language and learn about its ecosystem takes time, don't forget it!&lt;/li&gt;
&lt;li&gt;Must stop idolizing Facebook, Google, Netflix and co. They can do shitty things and mistakes or at least things that don't match our needs and our teams. Stay critical. Don't use in a discussion &lt;em&gt;That's what Google does&lt;/em&gt; or &lt;em&gt;It's made by the bright folks at Facebook&lt;/em&gt;. Even bright teams can make mistakes and this tech or this way of doing things may not be a good fit for your team. See my point above.&lt;/li&gt;
&lt;li&gt;Can use other languages or framework other than the most popular ones and still be awesome persons and developers. Not everybody has to use JS everywhere every time. For instance, I like Python, some may like Ruby, others Java. Find something you like, use it in your day job if you can. Diversity in languages and frameworks is a good thing. Learn something else than what you are currently using so proudly. It can help you get a new perspective on things and make us better developers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks for reading! Keep coding and learning and be nice and empathic ;-) Don't hesitate to react in the comment.&lt;/p&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category></entry><entry><title>Feedback after switching to openSUSE Tumbleweed</title><link href="//www.jujens.eu/posts/en/2020/May/15/feedback-after-switching-tumbleweed/" rel="alternate"></link><published>2020-05-15T00:00:00+02:00</published><updated>2020-05-15T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-05-15:/posts/en/2020/May/15/feedback-after-switching-tumbleweed/</id><summary type="html">&lt;p&gt;This article is a follow up to &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Feb/23/opensuse-install-btrfs-subvolumes/"&gt;Installing openSUSE next to Fedora with BTRFS&lt;/a&gt; where I detailed how I switched to openSUSE Tumbleweed.
In this article, now that I have been using Tumbleweed for about 2 months and a half, I'll give some feedback on my experience.&lt;/p&gt;
&lt;p&gt;The issues I …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This article is a follow up to &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Feb/23/opensuse-install-btrfs-subvolumes/"&gt;Installing openSUSE next to Fedora with BTRFS&lt;/a&gt; where I detailed how I switched to openSUSE Tumbleweed.
In this article, now that I have been using Tumbleweed for about 2 months and a half, I'll give some feedback on my experience.&lt;/p&gt;
&lt;p&gt;The issues I had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;For some reason, I lost an EFI file used by Fedora to boot which prevented me to run my Fedora installation. I was able to restore it by copying another EFI file (&lt;tt class="docutils literal"&gt;mmx.efi&lt;/tt&gt;) into the proper location.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Unlocking the LUCKS drive in Grub is slow. Although I find it's a bit faster lately (and it's not an issue with Tumbleweed per say).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Docker sometimes fails to pull images. It only happens in script, running &lt;tt class="docutils literal"&gt;docker pull SOME_IMAGE&lt;/tt&gt; always runs correctly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Unlike in Fedora, &lt;tt class="docutils literal"&gt;/tmp&lt;/tt&gt; is not cleaned automatically after a reboot. You have to enable this manually by putting the content below in &lt;tt class="docutils literal"&gt;/etc/tmpfiles.d/tmp.conf&lt;/tt&gt; (see &lt;a class="reference external" href="https://forums.opensuse.org/showthread.php/535050-tmp-amp-var-tmp-safe-to-remove?p=2895079#post2895079"&gt;this thread&lt;/a&gt; for the solution and the reasoning behind it):&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code aconf literal-block"&gt;
&lt;span class="c"&gt;#  This file is part of systemd.&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;#  systemd is free software; you can redistribute it and/or modify it&lt;/span&gt;
&lt;span class="c"&gt;#  under the terms of the GNU Lesser General Public License as published by&lt;/span&gt;
&lt;span class="c"&gt;#  the Free Software Foundation; either version 2.1 of the License, or&lt;/span&gt;
&lt;span class="c"&gt;#  (at your option) any later version.&lt;/span&gt;

&lt;span class="c"&gt;# See tmpfiles.d(5) for details&lt;/span&gt;

&lt;span class="c"&gt;# Clear tmp directories separately, to make them easier to override&lt;/span&gt;
&lt;span class="c"&gt;# SUSE policy: we don't clean those directories&lt;/span&gt;
&lt;span class="nb"&gt;D&lt;/span&gt;! &lt;span class="sx"&gt;/tmp&lt;/span&gt; &lt;span class="m"&gt;1777&lt;/span&gt; root root -
&lt;span class="nb"&gt;q&lt;/span&gt; &lt;span class="sx"&gt;/var/tmp&lt;/span&gt; &lt;span class="m"&gt;1777&lt;/span&gt; root root -
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Updating the kernel to a new minor version (eg from 4.5 to 4.6) can break the Nvidia drivers and thus your display. The patched driver comes relatively fast but it was a bad surprise when it happened to me! I hope the process will be smother in the future. It was also the occasion to experiment booting from a read-only BTRFS snapshot. And it worked well!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite these issues (for which I have workarounds anyway), I am very pleased with my experience.
The update process works well (with the exception of Nvidia drivers as pointed above) and the system is stable.
So I decided to switch all my computers to it (I switched to a rolling release to avoid Fedora updates after all, didn't I?).&lt;/p&gt;
&lt;p&gt;I must also say that YAST (which acts as a configuration panel for you computer from firewall to installing packages) is well done and a pleasure to use.
No need to search/install different tools, just use YAST!&lt;/p&gt;
&lt;p&gt;I also find the use of openSUSE of BTRFS snapshots to be really cool.
I haven't used them much since the system is stable and I haven't encountered issues with updates (except once with Nvidia).
But it's still a nice thing.
I'll just note that while installing openSUSE to another computer, I made a big configuration mistake that locked me out of the system.
Thanks to the snapshots and the rollback mechanism, it wasn't such a big deal (because yes, &lt;tt class="docutils literal"&gt;/etc&lt;/tt&gt; will be in the snapshot too).
Without it, I might have needed to reinstall everything.
So I don't need them often, but I'm really glad they are here when I do.&lt;/p&gt;
&lt;p&gt;This post wouldn't be complete without some observation on KDE.
As a long time Gnome user, I also decided to switch to KDE to see how it goes (and while your changing, why not change more?).
I am pleased with the change and was able to adapt to KDE very quickly (despite many years of using Gnome).
I do appreciate the fact that many things are integrated by default (like the clipboard manager or media player integration) whereas you need extension in Gnome to do this.
I also really like the fact that the command that ask for the root password is mentioned on the popup that ask for it.
I think it is a big plus for security.&lt;/p&gt;
&lt;p&gt;I had some issues though, here is the list and how I solved them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;I cannot configure my gmail account to use it easily with KMail. From what I read, I have to enable IMAP support in gmail. In Gnome this is supported by default (calendar works fine though). Since I only have my professional mailbox in it, I can just keep gmail opened in a pined tab. So not a big deal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Since I use the same user on both Fedora and openSUSE, when KDE launched it changed some configuration and now the close, maximise and minimise icons looks a bit funny on Gnome.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;I use the &lt;a class="reference external" href="http://bepo.fr/wiki/Accueil"&gt;bépo&lt;/a&gt; keyboard disposition (which was made specifically for French). It was really easy to configure this keyboard disposition in the session but harder to enable it on the login screen (although it may come from the fact that openSUSE doesn't support this disposition during install unlike Fedora). Luckily, &lt;a class="reference external" href="https://forums.archlinux.fr/viewtopic.php?t=19684"&gt;this post on the ArchLinux forum&lt;/a&gt; had the solution: update &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/X11/xorg.conf.d/00-keyboard.conf&lt;/span&gt;&lt;/tt&gt; with the content below.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code aconf literal-block"&gt;
&lt;span class="nb"&gt;Section&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;InputClass&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;Identifier&lt;/span&gt;         &lt;span class="s2"&gt;&amp;quot;Keyboard Layout&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;MatchIsKeyboard&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;yes&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;MatchDevicePath&lt;/span&gt;    &lt;span class="s2"&gt;&amp;quot;/dev/input/event*&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;Option&lt;/span&gt;             &lt;span class="s2"&gt;&amp;quot;XkbLayout&amp;quot;&lt;/span&gt;  &lt;span class="s2"&gt;&amp;quot;fr&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;Option&lt;/span&gt;             &lt;span class="s2"&gt;&amp;quot;XkbVariant&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;bepo_latin9&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;Option&lt;/span&gt;             &lt;span class="s2"&gt;&amp;quot;XkbOptions&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;terminate:ctrl_alt_bksp&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;EndSection&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;I had to create a script in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.config/autostart-scripts/ssh-add.sh&lt;/span&gt;&lt;/tt&gt; with the content below to correctly pre-load my SSH keys, something that worked by default on Gnome. The script is based on &lt;a class="reference external" href="https://wiki.archlinux.org/index.php/KDE_Wallet#Using_the_KDE_Wallet_to_store_ssh_key_passphrases"&gt;this article from the ArchLinux wiki&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; key in &lt;span class="k"&gt;$(&lt;/span&gt;ls -d ~/.ssh/* &lt;span class="p"&gt;|&lt;/span&gt; grep -v pub &lt;span class="p"&gt;|&lt;/span&gt; grep -v authorized_keys &lt;span class="p"&gt;|&lt;/span&gt; grep -v config &lt;span class="p"&gt;|&lt;/span&gt; grep -v known_hosts &lt;span class="p"&gt;|&lt;/span&gt; grep -v seahorse&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    ssh-add -q &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also find the combo KDE + openSUSE to need less RAM that my Fedora + Gnome.&lt;/p&gt;
&lt;p&gt;So, to conclude, I am very pleased with the change and don't regret doing it.&lt;/p&gt;
</content><category term="Blog"></category><category term="Linux"></category></entry><entry><title>PWAs and Django</title><link href="//www.jujens.eu/posts/en/2020/Feb/29/django-pwa/" rel="alternate"></link><published>2020-02-29T00:00:00+01:00</published><updated>2020-02-29T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-02-29:/posts/en/2020/Feb/29/django-pwa/</id><summary type="html">&lt;p&gt;In this article, I'll guide you to create a &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Progressive_web_application"&gt;PWA&lt;/a&gt; with the &lt;a class="reference external" href="https://www.djangoproject.com/"&gt;Django framework&lt;/a&gt;.
All the code for this project is available under &lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/"&gt;my gitlab account&lt;/a&gt;.
You will find in each sections links to the relevant commits to help you follow.
If something is not clear or if you have …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In this article, I'll guide you to create a &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Progressive_web_application"&gt;PWA&lt;/a&gt; with the &lt;a class="reference external" href="https://www.djangoproject.com/"&gt;Django framework&lt;/a&gt;.
All the code for this project is available under &lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/"&gt;my gitlab account&lt;/a&gt;.
You will find in each sections links to the relevant commits to help you follow.
If something is not clear or if you have a question, please leave a comment below.&lt;/p&gt;
&lt;p&gt;Updates:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;On 2020-10-12: as pointed out by Ernest by email, the workbox version was missing the version number in the ServiceWorker. It is required to update it and recache pages. It is now fixed.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prerequisites" id="id1"&gt;Prerequisites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#pwa-basics" id="id2"&gt;PWA basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#building-a-pwa-with-django" id="id3"&gt;Building a PWA with Django&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-a-django-website" id="id4"&gt;Create a Django website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#adding-a-manifest-json" id="id5"&gt;Adding a manifest.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#adding-a-basic-serviceworker" id="id6"&gt;Adding a basic ServiceWorker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#is-this-a-pwa" id="id7"&gt;Is this a PWA?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#add-basic-caching" id="id8"&gt;Add basic caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#add-offline-support" id="id9"&gt;Add offline support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#caching-strategies" id="id10"&gt;Caching strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#cleaning-the-cache" id="id11"&gt;Cleaning the cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#suggestions-to-further-improve-dynamic-caching" id="id12"&gt;Suggestions to further improve dynamic caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#caching-pages-with-js-and-css" id="id13"&gt;Caching pages with JS and CSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#using-workox" id="id14"&gt;Using Workox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id15"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="prerequisites"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Prerequisites&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I expect you to be at ease with Django and to have some knowledge of modern JavaScript (ES6+).
You don't need much JavaScript: basic knowledge, fat arrow functions and Promise should be enough.
No pre-requisites on PWA are required, this article includes a section to demystify them if needed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pwa-basics"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;PWA basics&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Simply put, PWAs are &amp;quot;installed&amp;quot; web pages: when you browse on a website that is a PWA, you will be prompted to install it.
If you accept, you will see the icon of the APP on your home screen (like any other app) and if you press this icon, the PWA will launch in full screen mode just like a native app.
But you didn't go to the app store to install it.
It's still just a website.&lt;/p&gt;
&lt;p&gt;As a developer, building a PWA means:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Your users don't have to install it: they can use the app directly on the website without installing anything and you'll still be able to provide them advanced features like caching and offline support.&lt;/li&gt;
&lt;li&gt;You will have more control on when you can update it: no need to submit it to the app store and wait for validation. Just push files to you server. The update will occur the next time your users reopen the app.&lt;/li&gt;
&lt;li&gt;You are not bound by the rules of any app stores.&lt;/li&gt;
&lt;li&gt;The app will work on any device with a recent browser.
Chrome has the best support for PWAs right now, Firefox is quite good but Safari support can be an issue (even if it's getting better, see &lt;a class="reference external" href="https://medium.com/&amp;#64;firt/whats-new-on-ios-12-2-for-progressive-web-apps-75c348f8e945"&gt;this article for instance&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;The app can be progressively enhanced (eg by adding better offline support or better caching).&lt;/li&gt;
&lt;li&gt;You show notifications the user with the &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/notification"&gt;Notification API&lt;/a&gt; and  the &lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/Push_API"&gt;Push API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can access &lt;em&gt;some&lt;/em&gt; native features (like the camera or the microphone). If you want to access all native features or require very high performance (for a video game for instance), you still need to do a native app.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are the basic components needed to make a PWA:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;manifest.json&lt;/tt&gt;: it's a JSON file describing how the app must be displayed and installed. You'll use it to specify the name, icon, orientation and some display properties of your app. See &lt;a class="reference external" href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json"&gt;here&lt;/a&gt; for more details. &lt;em&gt;It is required to make your app a PWA.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ServiceWorker&lt;/tt&gt; (SW for short): it behaves like a proxy server between your app and the network. It will keep working even when the tab is closed. So it will allow you to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Have caching and offline support.&lt;/li&gt;
&lt;li&gt;Sync things in the background.&lt;/li&gt;
&lt;li&gt;Subscribe to notifications of the Push API and display them to users.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please note that:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;It only works over HTTPS (except for localhost so you can develop without certificates).&lt;/li&gt;
&lt;li&gt;It cannot access the DOM.&lt;/li&gt;
&lt;li&gt;It may apply to all or only a subset of your site.&lt;/li&gt;
&lt;li&gt;It must be registered to have an effect.&lt;/li&gt;
&lt;li&gt;It will only get updated if its content changed and after the tab is closed and reopen (unless you use the dev tools and force it to reload on change but that's not an option for your users, more on that below).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/Service_Worker_API"&gt;here&lt;/a&gt; for more. &lt;em&gt;It is required to make your app a PWA.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt;: where you put data to exchange with the SW (SW cannot access &lt;tt class="docutils literal"&gt;localStorage&lt;/tt&gt;). See &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API"&gt;here&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Many other APIs I'll just list here so you know what you can do:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/notification"&gt;Notification API&lt;/a&gt; to display notification to the user.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/Push_API"&gt;Push API&lt;/a&gt; to receive messages from a server.&lt;/li&gt;
&lt;li&gt;Many more: geolocation, camera access, …&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;This section is heavily inspired from the similar section from my article &lt;a class="reference external" href="//www.jujens.eu/posts/en/2019/Sep/01/aurelia-pwa/"&gt;Writing a PWA with Aurelia&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="building-a-pwa-with-django"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Building a PWA with Django&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="create-a-django-website"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Create a Django website&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Obvious isn't it?
For the purpose of this tutorial, I created a basic site with Django and a few pages.
You can of course follow the following sections to add PWA support to your own site.&lt;/p&gt;
&lt;p&gt;The repository with all the code is located &lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa"&gt;here&lt;/a&gt;.
To use the project, you will need to create a virtual environment and install Django in it.
The code was tested with Django 2.2 but it should work correctly with any more recent versions of Django.
You can install the project with &lt;a class="reference external" href="https://pipenv.kennethreitz.org/en/latest/"&gt;Pipenv&lt;/a&gt;:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Installation of the dependencies: &lt;tt class="docutils literal"&gt;pipenv install&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Run the default migrations (this will create a SQlite database): &lt;tt class="docutils literal"&gt;pipenv run python manage.py migrate&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Start the server: &lt;tt class="docutils literal"&gt;pipenv run python manage.py runserver&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The commits associated with this section (nothing relating with PWA so far):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/bce959cad77ed3e6edf115f2d04ed221c22fbdb9"&gt;Bootstrap Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/8c7dc054159f302d8611b69d20690307d531fca9"&gt;Add basic views to create basic pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/2c4eab9a2a6ae68a720e39d4f0b2f3f03d52681c"&gt;Add dynamic view&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/9594eac5531ebd83c74bd0df327ab08088f55e0d"&gt;Add dynamic pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="adding-a-manifest-json"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Adding a manifest.json&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As said in the previous section, the manifest is a JSON file that will allow your app to be installed.
Since its content shouldn't change often, I think we can include in in the static folder with hard-coded values.&lt;/p&gt;
&lt;p&gt;You can find Django apps that will allow you to configure this with settings variable but I don't recommend them.
The file is simple and rarely changes, so I don't think it's worth adding a dependency to you project just for that.&lt;/p&gt;
&lt;p&gt;In my case, it is in &lt;tt class="docutils literal"&gt;djangopwa/static/manifest.json&lt;/tt&gt; with this content:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Django PWA&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;djangopwa&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;start_url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;scope&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;display&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;standalone&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;background_color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;#FFF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;theme_color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;#493174&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Test app for Django and PWA&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;dir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;lang&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;en-US&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;orientation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;portrait-primary&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;icons&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/static/icons/aurss.96x96.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;image/png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;sizes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;96x96&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/static/icons/aurss.512x512.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;image/png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;sizes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;512x512&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We can now update our base template to load it on every page:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="c"&gt;&amp;lt;!-- This is to defined the viewport and how the app must behave when on full screen. This is required too. --&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;viewport&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;width=device-width, initial-scale=1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;manifest&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{% static 'manifest.json' %}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;While we are at it, we can also update our base template to add better compatibility with IE11 and Safari by adding:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;theme-color&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#493174&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;apple-touch-icon&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{% static 'icons/aurss.192x192.png' %}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now your app can be installed on the home screen but it's not a PWA yet.
It's missing a ServiceWorker.
That's the subject of the next section.&lt;/p&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/fdf7519b2105e0bb3c0f3ff5aa1340f9dad2c57f"&gt;Add manifest.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/3fbedc5644d1af16c04b991600b58db871dc0222"&gt;Improve base template to optimize PWA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="adding-a-basic-serviceworker"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Adding a basic ServiceWorker&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The service worker is defined in a JavaScript file that must be served at the root of your application.
If it is under &lt;tt class="docutils literal"&gt;/static&lt;/tt&gt; its URL will be something like &lt;tt class="docutils literal"&gt;/static/sw.js&lt;/tt&gt;.
It means that the scope of your &lt;tt class="docutils literal"&gt;ServiceWorker&lt;/tt&gt; (ie the pages it is activated on), must be under &lt;tt class="docutils literal"&gt;/static&lt;/tt&gt;.
This means that it won't be enabled for our whole site (which is what we want, limiting it to &lt;tt class="docutils literal"&gt;/static&lt;/tt&gt; makes it unusable on standard pages so it would be quite useless).
So it must be served from something like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://wwww.example.com/sw.js&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;To achieve this, I created a simple &lt;tt class="docutils literal"&gt;TemplateView&lt;/tt&gt; that will serve a file named &lt;tt class="docutils literal"&gt;sw.js&lt;/tt&gt;.
The file is created from a template.
It will also be interesting to have a template for this later.&lt;/p&gt;
&lt;p&gt;We do this by adding the following code into our main URL file &lt;tt class="docutils literal"&gt;djangopwa/urls.py&lt;/tt&gt;:&lt;/p&gt;
&lt;!-- code:: python

# We specify the content type so it is correctly set to JavaScript.
path(
    'sw.js',
    TemplateView.as_view(template_name='sw.js', content_type='application/javascript'),
    name='sw.js',
), --&gt;
&lt;p&gt;Then, in &lt;tt class="docutils literal"&gt;djangopwa/templates/sw.js&lt;/tt&gt;, we can add the basic structure of our ServiceWorker:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// Bump this version number each time a cached or asset changes.
// If you don't, the SW won't be reinstalled and the pages you cache initially won't be updated
// (by default at least, see next sections for more on caching).
&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{{ version }}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'install'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Installing SW version:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/7c1211a95153186815a3c0504fd12b651f84b5d2"&gt;Add ServiceWorker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/e7db83eddebd6ad4cdcab41b43c3a6ab0ebe9892"&gt;Rely on project version to set SW version&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="is-this-a-pwa"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Is this a PWA?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We should check shouldn't we?
The easiest way to do this is to open Chrome and open the dev tools (although other browsers support PWA, Chrome right now provides the best developer experience with its &lt;em&gt;Audits&lt;/em&gt; and  &lt;em&gt;Application&lt;/em&gt; tabs).
Open the &lt;em&gt;Audits&lt;/em&gt; tab, make sure &lt;em&gt;Progressive Web App&lt;/em&gt; is selected under the &lt;em&gt;Audits&lt;/em&gt; section and run one.
The only problematic item should be &lt;em&gt;Does not redirect HTTP traffic to HTTPS&lt;/em&gt; which is normal since we are running the application locally without HTTPS.&lt;/p&gt;
&lt;img alt="" src="/static/django-pwa/pwa_audit.png" style="width: 600px;" /&gt;
&lt;p&gt;So yes, we successfully made a PWA.
A very basic one we will improve in the upcoming sections.
And you know the last item you'll have to respect before putting it into production: serve it under HTTPS and make sure all HTTP traffic is redirected to HTTPS.&lt;/p&gt;
&lt;p&gt;Before going further, I'd like to present to you the &lt;em&gt;Application&lt;/em&gt; tab of the Chrome dev tools.
When working with a PWA, it will be the most useful tab.
It allows you to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Inspect the manifest.&lt;/li&gt;
&lt;li&gt;Manage the service worker.
I suggest you tick &lt;em&gt;Update on reload&lt;/em&gt; to update the Service Worker each time it is modified and you reload the page.
If you don't, you will have to close the tab and open it again for the Service Worker to update which is cumbersome during development.
If you have issue with this option, disable it, close the tab and reopen it to trigger a standard update of the ServiceWorker.&lt;/li&gt;
&lt;li&gt;See the content of the various storage.&lt;/li&gt;
&lt;li&gt;Inspect and flush the cache storage where the Service Worker will save the content of your HTTP requests.
This is very handy when testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="add-basic-caching"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id8"&gt;Add basic caching&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now we can cache some pages and serve the pages from the cache instead of from the network.
The pages will be added in the cache when the SW is installed (they will be pre-cached) and won't be updated afterwards.
Pre-caching is interesting for pages you know will be accessed or for static assets.
We will handle updates later.&lt;/p&gt;
&lt;p&gt;To do so, we will update the function that reacts to the &lt;tt class="docutils literal"&gt;install&lt;/tt&gt; event (which is triggered when the SW installs) to pre-cache some pages:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{{ version }}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;staticCachePrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'static'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;staticCacheName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;staticCachePrefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;staticCacheName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Caching app shell'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// All the pages supplied here will be set in the cache when the service worker installs.
&lt;/span&gt;            &lt;span class="c1"&gt;// If the service worker is updated, these pages will be updated in the cache.
&lt;/span&gt;            &lt;span class="c1"&gt;// So it can be a good idea to inject the version of the project in the template
&lt;/span&gt;            &lt;span class="c1"&gt;// to be sure the SW will be updated (and thus the pre-cached assets) when the project is.
&lt;/span&gt;            &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addAll&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="s1"&gt;'/static/manifest.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'/offline/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Then we must add an event listener for the &lt;tt class="docutils literal"&gt;fetch&lt;/tt&gt; event so we can respond with the pages from the cache.
This event is triggered each time the browser tries to do an HTTP request when you click on a link or use the &lt;tt class="docutils literal"&gt;fetch&lt;/tt&gt; API (don't use the &lt;tt class="docutils literal"&gt;xhr&lt;/tt&gt; object or &lt;tt class="docutils literal"&gt;jQuery.ajax&lt;/tt&gt;, it doesn't fit well with SW because the &lt;tt class="docutils literal"&gt;fetch&lt;/tt&gt; event is not triggered).
We can do this by adding the code below in the &lt;tt class="docutils literal"&gt;sw.js&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fetch'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Let the browser do its default thing
&lt;/span&gt;    &lt;span class="c1"&gt;// for non-GET requests. It's not safe to cache them anyway.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// If we have the response in the cache, we return it.
&lt;/span&gt;                &lt;span class="c1"&gt;// If not, we try to fetch it.
&lt;/span&gt;                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pre-caching is nice but you will most likely have many dynamic pages on your site and you can't pre-cache them all (most of them won't be accessed by your user anyway).
But you may still want to cache them.
If you don't want to cache all of them, you can rely on &lt;tt class="docutils literal"&gt;event.request.url&lt;/tt&gt; to test if the page must be cached or not.
By slightly updating the handler above, we can cache dynamic pages:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// Move this line with the constants at the top of the file.
&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamicCacheName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'dynamic'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`[SW] Requesting &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// If we have the response in the cache, we return it.
&lt;/span&gt;            &lt;span class="c1"&gt;// If not, we try to fetch it.
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`[SW] Served response to &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; from the cache.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dynamicCacheName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="c1"&gt;// We can read a response only once. So if we don't clone it here,
&lt;/span&gt;                            &lt;span class="c1"&gt;// we won't be able to see anything in the browser.
&lt;/span&gt;                            &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                        &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Warning: app is offline'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Tada, you can now cache any page. Be sure to use a different cache for the dynamic pages. It will be useful later when we will clean the cache. To test this, you can go to any URLs like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/say-something/SOMETHING&lt;/span&gt;&lt;/tt&gt;. If you use &lt;tt class="docutils literal"&gt;hi&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;bye&lt;/tt&gt; you will see the page. Otherwise, you will see a 404.&lt;/p&gt;
&lt;p&gt;This version has a problem though.
It will cache all pages even if the request fails (with a 500 or a 404 for instance).
So we will cache pages we don't want to cache.
To avoid this, before &lt;tt class="docutils literal"&gt;return caches.open(dynamicCacheName)&lt;/tt&gt;, you can add the code below to answer with the raw request with the request failed:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestSucceeded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;requestSucceeded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/248a62e0071c2efb2a2411725618a241da668cfc"&gt;Make the SW cache basic pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/b3b6e5d3f06e980028060b81f9df98c5eab4132d"&gt;Can serve dynamic requests from the cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/42ae7afddf19a55555eccf28ef2e4683ca8c897d"&gt;Don't cache requests that didn't succeed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="add-offline-support"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id9"&gt;Add offline support&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that we have setup caching, we can provide offline support to our user.
If the network is down, we will display them a page explaining they are currently offline instead of displaying the error page from the browser.
To do so, we will once again update the handler associated with the &lt;tt class="docutils literal"&gt;fetch&lt;/tt&gt; event.
We will replace the line &lt;tt class="docutils literal"&gt;.catch(err =&amp;gt; &lt;span class="pre"&gt;console.warn('Warning:&lt;/span&gt; app is offline', &lt;span class="pre"&gt;err));&lt;/span&gt;&lt;/tt&gt; by the code below:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Network request failed, app is probably offline'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;staticCacheName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// If the request expects an HTML response, we display the offline page.
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'accept'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'text/html'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/offline/'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] failed to get response from network and cache.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now, in the dev tools, go offline (you may have to un-tick &lt;em&gt;Update on reload&lt;/em&gt; to witness the proper behavior and to re-open the tab).
You can do this in the &lt;em&gt;Network&lt;/em&gt; tab under or in the &lt;em&gt;Application&lt;/em&gt; tab under &lt;em&gt;Service Workers&lt;/em&gt;.
Navigate to a new page (that's not in the cache, for instance &lt;tt class="docutils literal"&gt;/toto&lt;/tt&gt;).
You should see your offline page.
Go back online, refresh the page and you should see the standard 404 page from Django.&lt;/p&gt;
&lt;p&gt;The commit associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/d2d9d3a4aab1033fd9787beb76d4d05a47708b40"&gt;Display offline page when app is offline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/1608ea137a1c80163c6df69f94f864549eb5d3f4"&gt;Fix response in offline mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="caching-strategies"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id10"&gt;Caching strategies&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That's all very interesting, but right now, if a page of your site updates and it is in the cache, you must remove it from the cache with the dev tools and reload the page to see the update.
Not very practical and none of your users will do this.
So we need to tune our caching strategy.
Let's detail them now so we know what to choose.&lt;/p&gt;
&lt;p&gt;They are various strategies you can implement:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Network only: always go to the network, cache nothing. That's the default behaviour.&lt;/li&gt;
&lt;li&gt;Cache only: always go to the cache, never reach the network.&lt;/li&gt;
&lt;li&gt;Cache with network fallback: if the response is in the cache, use it. Otherwise, go to the network. That's what we are using now.&lt;/li&gt;
&lt;li&gt;Network with cache fallback: try to use the network, if it fails, use the cache. If the network is slow, the requests will take time to fail so this will provide a poor experience.&lt;/li&gt;
&lt;li&gt;Cache then network: give the response that's in the cache (if present) to answer fast then make an HTTP request to update the cache.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The strategy to use depends on what kind of app you are building, the type of content associated with the URL, the domain you are requesting (yours or someone else's)…
I can't give you a general answer.&lt;/p&gt;
&lt;p&gt;I can strongly suggest you to never cache any request that's not a GET request: if a request have sides effects (PUT, POST, PATCH), it's not safe to cache the results.
It's common HTTP wisdom and practice.
However, you can rely on the Service Worker to save the payload of a POST in &lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt; when the network is down so you can do the request once the network is back online.
I won't talk about it in this article.
If you are interested, I have &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/master/src/sw.js#L50"&gt;an example&lt;/a&gt; in a small app I built.&lt;/p&gt;
&lt;p&gt;Here, I'll propose a slight variation of the &lt;em&gt;Network witch cache fallback&lt;/em&gt;: we will try to reach the network to provide the most up to date version of the page but if it fails within a timeout, then we will provide the version from the cache.
If the request were to succeed anyway, we will update the cache.
It looks like a good compromise.&lt;/p&gt;
&lt;p&gt;Before implementing this, I added a view that responds in a variable amount of time between 0s and 10s to easily simulate a page that takes time to respond.
You can access it under &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/random-response&lt;/span&gt;&lt;/tt&gt;.
I also refactored the code of the Service Worker a bit to clarify the code and ease the implementation.
Now each &amp;quot;step&amp;quot; is in their own functions: &lt;tt class="docutils literal"&gt;getFromCache&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;tryToFetchAndSaveInCache&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;fetchAndSaveInCache&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;provideOfflineFallback&lt;/tt&gt;.
You can find links to the relevant commits below, I won't detail in the article.&lt;/p&gt;
&lt;p&gt;Now that it's done, I can create a new function &lt;tt class="docutils literal"&gt;networkThenCache&lt;/tt&gt; that does what we wish to implement:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// In milliseconds.
&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;networkWaitTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;networkThenCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="nx"&gt;tryToFetchAndSaveInCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dynamicCacheName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;networkWaitTime&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getFromCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;provideOfflineFallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;With &lt;tt class="docutils literal"&gt;Promise.race&lt;/tt&gt; returns a promise that will resolve when the first promise in the array we give it resolves.
So here, it will resolve when we get a response from the network or after 2s with the response from the cache.
If we don't have a response in the cache, we will display the offline fallback.
It's not perfect: if you don't have a response in the cache you may want to wait more for the network to respond.
But at least it's a start and you can adapt it to fit your needs.&lt;/p&gt;
&lt;p&gt;We also have to update our response to the &lt;tt class="docutils literal"&gt;fetch&lt;/tt&gt; event:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;networkThenCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now if you go to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/random-response&lt;/span&gt;&lt;/tt&gt;, you will see (the time spent sleeping in the view is displayed in the console and on the page):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The offline page if the first response takes too much time.&lt;/li&gt;
&lt;li&gt;The response supplied by the view if it answered in less than 2s.&lt;/li&gt;
&lt;li&gt;The response from the cache if the view took more than 2s.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One interesting thing is that since promise chains can't be cancelled, if the network request do succeed, it will update the cache.
You can test it and see in if you inspect the dynamic cache of the application.&lt;/p&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/c64740f1f7fdc77855da37eb060406dc70a8b56d"&gt;Add a view which responds in a random number of time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/82e8c3da005c0a5ae26af4debd1ffc7afd38911e"&gt;Split fetch event callback into multiple functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/270aca3f6ad5dfa2f333c844026ddcd7b6bffe4f"&gt;Increase logging in SW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/b45c1e5d4b2127bc92a1a51c1d4e9c8caf420841"&gt;Implement the network then cache strategy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="cleaning-the-cache"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id11"&gt;Cleaning the cache&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We have to kind of caches to clean: the static cache and the dynamic cache.
We'll start with the static cache.&lt;/p&gt;
&lt;p&gt;The easier way to clean it, is to remove all static caches that are not it.
Since we made a clear separation between static and dynamic caches with a prefix, all we need to do is:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'activate'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Cleaning old cache shell'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;keys&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;staticCacheName&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;staticCachePrefix&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Cleaning the dynamic cache is a bit trickier.
We would like to remove the oldest entries first.
You can access all entries in the cache with &lt;tt class="docutils literal"&gt;cache.keys()&lt;/tt&gt; but you don't have access to the time the item was added to the cache.
And you can't rely on the order because it appears to be somewhat random.
Furthermore, it is impossible to read headers of a request once it has been cached.
Even before, only a small subsets of headers (those viewed as safe) are available.
See: &lt;a class="reference external" href="https://stackoverflow.com/a/59152482"&gt;this&lt;/a&gt; and &lt;a class="reference external" href="https://stackoverflow.com/a/47130151"&gt;this&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What can we do?
They are several ways to walk around this:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Just remove entries until we have an acceptable amount of them in the cache. That's quick and dirty but it's really simple to implement.&lt;/li&gt;
&lt;li&gt;Until a service worker is updated it keeps all objects in memory (you can't see this behavior if &lt;em&gt;Update on reload&lt;/em&gt; is ticked). So we can create a map mapping a URL to its response timestamp and use that to find the response to delete. We will also have to delete entries in the dynamic cache we don't know about (or delete the dynamic cache entirely upon installation). From what I read &lt;a class="reference external" href="https://github.com/GoogleChrome/workbox/blob/e1265e83343affd988ab050e83fef66f6ca62830/packages/workbox-cache-expiration/CacheExpirationPlugin.mjs"&gt;here&lt;/a&gt;, this is how the workbox plugin (a plugin to ease working with ServiceWorkers by google, I talk about it in the &lt;a class="reference internal" href="#using-workox"&gt;Using Workox&lt;/a&gt; section) actually works.&lt;/li&gt;
&lt;li&gt;Store the mapping information in &lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt; so it persists between updates of the ServiceWorker and delete the entries based on that.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As much as I would like to introduce &lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt; in this tutorial, I'll go for solution 2 which is more straightforward (and I think this tutorial is already long enough).&lt;/p&gt;
&lt;p&gt;To do so, we will add a constant describing how much items we want to keep in the cache and create a map to keep the association between the requested URLs and the date at which they were seen:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxNumberItemsDynamicCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urlsToCacheTimes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We now must update it each time we put a response in the dynamic cache and launch a clean:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;urlsToCacheTimes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;trimCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxNumberItemsDynamicCache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlsToCacheTimes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And we must add the function to clean the cache:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;trimCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxItems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cacheTimeInfos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheTimeInfos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;maxItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Nothing to trim from the cache.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// We sort all entries by descending dates.
&lt;/span&gt;    &lt;span class="c1"&gt;// We keep a slice of the maxItems more recent items.
&lt;/span&gt;    &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urlsToKeep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cacheTimeInfos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxItems&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Keeping in cache'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;urlsToKeep&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deletions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;urlsToKeep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`[SW] Removing &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt; from the cache.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nx"&gt;cacheTimeInfos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deletions&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Done trimming cache.'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Error while trimming cache.'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;You should be able to read the &lt;tt class="docutils literal"&gt;Date&lt;/tt&gt; header from the response with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;res.headers.get('Date')&lt;/span&gt;&lt;/tt&gt; if you prefer to rely on the date given by the server.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/822ae00e4f18f64ed7b0ad1e136396424d6d84ed"&gt;Add view to easily fill the dynamic cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/c81e1288178536028490e7a984769a520a3c2363"&gt;Clean dynamic cache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="suggestions-to-further-improve-dynamic-caching"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id12"&gt;Suggestions to further improve dynamic caching&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can read the HTTP header from the responses to fine tune how you cache a page.
For instance, we will not cache a page if it contains the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;no-cache&lt;/span&gt;&lt;/tt&gt; value in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Control-Cache&lt;/span&gt;&lt;/tt&gt; header.
To do so, we will update the &lt;tt class="docutils literal"&gt;fetchAndSaveInCache&lt;/tt&gt; function:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestSucceeded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mustNotCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cache-control'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'no-cache'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;requestSucceeded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] Request failed.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mustNotCache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[SW] The page must not be cached.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can of course use headers in more advance ways: to invalidate the cache based on what the response tells you to do or to fetch a resource directly from the cache if the header allows you.&lt;/p&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Astuce&lt;/p&gt;
&lt;p class="last"&gt;You can list all the headers of a response with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Array.from(res.headers.entries()))&lt;/span&gt;&lt;/tt&gt;. This must be run before the response is cached (as stated above).&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/506bfa75b6709adcfe5e47bc2fd1bf394f19e75a"&gt;Add view that must never be cached&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/01f4b244ef5b301aa66fe49b65018a2cfa92b14a"&gt;Cache response based on Cache-Control header&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="caching-pages-with-js-and-css"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id13"&gt;Caching pages with JS and CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So far so good.
But our application is lacking styling and JavaScript!
To illustrate how it goes, we will only add some CSS to the site.
The process for JavaScript is the same.&lt;/p&gt;
&lt;p&gt;Let's add some basic style in &lt;tt class="docutils literal"&gt;djangopwa/static/style.css&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code css literal-block"&gt;
&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;thing-said&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And load it in &lt;tt class="docutils literal"&gt;base.html&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{% static 'style.css' %}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you reload the page, you should see all the titles in grey and the file &lt;tt class="docutils literal"&gt;style.css&lt;/tt&gt; will be added to the dynamic cache.
It's looking quite good by default.&lt;/p&gt;
&lt;p&gt;Should we pre-cache it?
It's a file that will be requested for every page and that's required on the offline page too.
So it makes sense to pre-cache it.
But this lead to the question: what should we pre-cache?
Maybe it's time to answer.&lt;/p&gt;
&lt;p&gt;The general advise I've seen is to pre-cache:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The app shell. That's the resources (CSS and JS) that are required to display the base of the application. They most likely don't change very often and they are required to display all the pages (including our offline page). This means these files will be requested them anyway. So we don't waste anything by pre-loading them.&lt;/li&gt;
&lt;li&gt;The offline page because once offline we won't be able to load it! It also mean it's probably a good idea to keep it small and simple.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could cache other things too.
But I think for most cases that's all we need to pre-cache.
We don't want to request too many pages or files: they will all be downloaded when the app starts.
For our mobile users, we don't want to download too many things to save bandwidth, storage space and power.
Plus, we don't know what the users will access so we may cache stuff that's not required.
And for the normal pages of the site, we have the dynamic cache to speed things up.&lt;/p&gt;
&lt;p&gt;Because these resources are pre-cached, we can switch to a cache only strategy: each time they are requested we load them from the cache.
To avoid issues when you update them, you should make sure their names contain a hash of the file so we can keep them indefinitely.
It's a good practice anyway so your CDN can cache these assets indefinitely too.
This can be done easily in Django by using the proper static file storage: &lt;a class="reference external" href="https://docs.djangoproject.com/en/3.0/ref/contrib/staticfiles/#manifeststaticfilesstorage"&gt;the ManifestStaticFilesStorage&lt;/a&gt;.
You can enable it by adding in your setting file: &lt;tt class="docutils literal"&gt;STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'&lt;/tt&gt;.
You may want to disable this during development not to hit the cache and see the updated files.&lt;/p&gt;
&lt;p&gt;Here is how the &lt;tt class="docutils literal"&gt;ServiceWorkerView&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;sw.js&lt;/tt&gt; now looks:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServiceWorkerView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TemplateView&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;template_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sw.js'&lt;/span&gt;
    &lt;span class="n"&gt;content_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'application/javascript'&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'sw.js'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_context_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'version'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'icon_url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'icons/aurss.512x512.png'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'manifest_url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'manifest.json'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'style_url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'style.css'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'home_url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'home'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'offline_url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'offline'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appShell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ icon_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ manifest_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ style_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ home_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ offline_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;partialUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;//&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;partialUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;I could have used the &lt;tt class="docutils literal"&gt;static&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;url&lt;/tt&gt; template tags directly but that would have required to add &lt;tt class="docutils literal"&gt;{% load static %}&lt;/tt&gt; in &lt;tt class="docutils literal"&gt;sw.js&lt;/tt&gt;. Since this is not valid JS, my editor report it as an error which I find annoying.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/26fee9667eaf125739b705cf94633820e3711006"&gt;Configure static root&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/98d0a9667270726bcde027b1a87c8c024286980f"&gt;Make sure the app shell is always served from the cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/52e2348418dce470aa7bd65cbbdbca87634a6a2f"&gt;Add basic styling to the application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/0759b80c6cd3646ac00e14e7d291c1c7b8ffac00"&gt;Rely on the template to render URLs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="using-workox"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id14"&gt;Using Workox&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;So far, we've all done everything by hand.
It's interesting and it's a very good way to learn.
However, it can take a lot of time.
Here comes &lt;a class="reference external" href="https://developers.google.com/web/tools/workbox"&gt;Workbox&lt;/a&gt; a tool made by google to automate much of the process.
Google describe it as a &lt;em&gt;JavaScript Libraries for adding offline support to web apps&lt;/em&gt;.
If you search about PWAs you will probably hear about it as it's quite popular and feature complete.&lt;/p&gt;
&lt;p&gt;Since the documentation is very complete, I'll just provide an example of ServiceWorker using Workbox with a CDN to help you getting started.
It should provide more or less the same features than what we wrote by hand.
It's much smaller though (and probably less buggy).
The code is on the &lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/tree/workbox"&gt;workbox branch&lt;/a&gt; of the repository.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;importScripts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://storage.googleapis.com/workbox-cdn/releases/5.0.0/workbox-sw.js'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{{ version }}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Yay! Workbox is loaded 🎉`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`Boo! Workbox didn't load 😬`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OFFLINE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'{{ offline_url }}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appShell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ icon_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ manifest_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ style_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ home_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'{{ offline_url }}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;partialUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;//&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;partialUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Precache the shell.
&lt;/span&gt;&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;precaching&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;precacheAndRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appShell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;revision&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})));&lt;/span&gt;

&lt;span class="c1"&gt;// Serve the app shell from the cache.
&lt;/span&gt;&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerRoute&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;appShell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CacheOnly&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Serve the other pages from the cache and make a request to update the value in the cache.
// Limit the cache to 5 entries.
&lt;/span&gt;&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;appShell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strategies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StaleWhileRevalidate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;cacheName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'dynamic-cache'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpirationPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nx"&gt;maxEntries&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;})],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Handle offline.
// From https://developers.google.com/web/tools/workbox/guides/advanced-recipes#provide_a_fallback_response_to_a_route
&lt;/span&gt;&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setCatchHandler&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OFFLINE_URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The commits associated with this section:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/0793fafc0d78202e6e417d309746612a013ef21d"&gt;Switch to workbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;` Put version number in workbox version  &amp;lt;&lt;a class="reference external" href="https://gitlab.com/Jenselme/django-pwa/-/commit/b3d13d3302813294db8eb85252b1a5d4eae46d0b"&gt;https://gitlab.com/Jenselme/django-pwa/-/commit/b3d13d3302813294db8eb85252b1a5d4eae46d0b&lt;/a&gt;&amp;gt;`__&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id15"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That was quite a journey!
Normally you should now be able to create a PWA with Django from scratch.
You should also be able to understand the main concepts of a PWA.
And you'll probably want to use Workbox to ease the writing of the ServiceWorker in your own app.
But learning how it works behind the scene will ease debugging and understanding of the documentation of Workbox.&lt;/p&gt;
&lt;p&gt;If you have any remarks or questions, please leave a comment below.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="Python"></category><category term="Django"></category><category term="PWA"></category><category term="JavaScript"></category></entry><entry><title>Installing openSUSE next to Fedora with BTRFS</title><link href="//www.jujens.eu/posts/en/2020/Feb/23/opensuse-install-btrfs-subvolumes/" rel="alternate"></link><published>2020-02-23T00:00:00+01:00</published><updated>2020-02-23T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-02-23:/posts/en/2020/Feb/23/opensuse-install-btrfs-subvolumes/</id><summary type="html">&lt;p&gt;Update: &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/May/15/feedback-after-switching-tumbleweed/"&gt;My feedback article&lt;/a&gt; is now available.&lt;/p&gt;
&lt;p&gt;I wanted to install openSUSE Tumbleweed (the rolling release version of openSUSE) on one of my computers to see how it looked outside a VM (and thus to try to use it daily).
I am thinking about switching to this distribution to avoid …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Update: &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/May/15/feedback-after-switching-tumbleweed/"&gt;My feedback article&lt;/a&gt; is now available.&lt;/p&gt;
&lt;p&gt;I wanted to install openSUSE Tumbleweed (the rolling release version of openSUSE) on one of my computers to see how it looked outside a VM (and thus to try to use it daily).
I am thinking about switching to this distribution to avoid major updates of Fedora.
They happen every 6 months and I have multiple machines to update, so I find it cumbersome to update them all (and I like to test new stuff too ^^).&lt;/p&gt;
&lt;p&gt;Why openSUSE? Because it looks stable, well tested, it provides a graphical installer (I already installed Arch and Gentoo in the past and wasn't enthusiastic about doing this again) and has some nice defaut with BTRFS (snapshots and booting from snapshots without having to configure it manually).
I also know a contributor and a long time user of openSUSE and Tumbleweed who's very happy about the system.&lt;/p&gt;
&lt;p&gt;In this article, I'll explain how I installed it next to my Fedora (which I don't want to loose it until I commit to making the switch).
Some things are specific to my setup, others are more generic and should be reusable (more or less easily).
If you have any question or remark, please leave a comment.
I'll assume you have some knowledge of BTRFS.&lt;/p&gt;
&lt;div class="section" id="starting-point"&gt;
&lt;h2&gt;Starting point&lt;/h2&gt;
&lt;p&gt;I had fedora installed with a BTRFS top level volume and 3 child volumes &lt;tt class="docutils literal"&gt;root&lt;/tt&gt; for &lt;tt class="docutils literal"&gt;/&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;var&lt;/tt&gt; for &lt;tt class="docutils literal"&gt;/var&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;home&lt;/tt&gt; for &lt;tt class="docutils literal"&gt;/home&lt;/tt&gt;.
Since I use docker with the BTRFS driver I also had many subvolumes of &lt;tt class="docutils literal"&gt;/var&lt;/tt&gt; for docker.&lt;/p&gt;
&lt;p&gt;I also installed Tumbleweed in a VM to see how it behaves.
I created another VM with Fedora installed just like on my computer so I could try installing Tumbleweed next to it without breaking my current setup.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="preparing-fedora"&gt;
&lt;h2&gt;Preparing Fedora&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;I removed the docker containers and images as well as all docker related subvolumes that remained. I don't know whether this could have an impact and didn't want to risk it (nor did I wish to migrate them).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The two most useful commands you can use at anytime to check something are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;btrfs subvolume list PATH&lt;/tt&gt; to list all subvolumes in the supplied filesystem.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;btrfs subvolume show PATH&lt;/tt&gt; to see which subvolume is mounted under the supplied path.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Disable SELinux: it's not used in openSUSE so I think some files will be mislabeled which may prevent Fedora to work properly (or maybe just prevent me to access some files, I don't know and I don't want to test). Let's simply as much as possible and remove it from the equation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Since my subvolumes are named &lt;tt class="docutils literal"&gt;var&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;root&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;home&lt;/tt&gt;, the Tumbleweed installer will mount them under &lt;tt class="docutils literal"&gt;/var&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;/root&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;/home&lt;/tt&gt;. I didn't find a way to prevent this. For &lt;tt class="docutils literal"&gt;/home&lt;/tt&gt; it's the behavior I&amp;nbsp;want since I want to keep my data. For the other two, it's not. You cannot rename subvolumes directly but you can rely on snapshots to achieve it. To do so, I (as root):&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Mounted the top level BTRFS volume (which is not accessible by default) with: &lt;tt class="docutils literal"&gt;mount &lt;span class="pre"&gt;-t&lt;/span&gt; btrfs &lt;span class="pre"&gt;-o&lt;/span&gt; subvolid=5 /dev/vda3 /mnt/toplevel/&lt;/tt&gt; (most of my commands are copied from when I tested in a VM, hence the &lt;tt class="docutils literal"&gt;vda&lt;/tt&gt;, adapt this part to your setup).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Created a snapshot for the &lt;tt class="docutils literal"&gt;root&lt;/tt&gt; subvolume: &lt;tt class="docutils literal"&gt;btrfs subvolume snapshot /mnt/toplevel/root/ /mnt/toplevel/fedoraroot/&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Emptied &lt;tt class="docutils literal"&gt;/mnt/toplevel/fedoraroot/var&lt;/tt&gt; to remove the directory with &lt;tt class="docutils literal"&gt;rmdir /mnt/toplevel/fedoraroot/var&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Created another snapshot for &lt;tt class="docutils literal"&gt;var&lt;/tt&gt; (I decided to make it a subvolume of &lt;tt class="docutils literal"&gt;fedoraroot&lt;/tt&gt; because I think it makes sense to have one top volume for Fedora): &lt;tt class="docutils literal"&gt;btrfs subvolume snapshot /mnt/toplevel/var/ /mnt/toplevel/fedoraroot/&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Migrated the nested subvolumes for &lt;tt class="docutils literal"&gt;/var&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[root&amp;#64;baley toplevel]# rmdir /mnt/toplevel/fedoraroot/var/lib/machines/
[root&amp;#64;baley toplevel]# btrfs subvolume snapshot /mnt/toplevel/var/lib/machines/ /mnt/toplevel/fedoraroot/var/lib/
[root&amp;#64;baley toplevel]# rmdir /mnt/toplevel/fedoraroot/var/lib/portables/
[root&amp;#64;baley toplevel]# btrfs subvolume snapshot /mnt/toplevel/var/lib/portables/ /mnt/toplevel/fedoraroot/var/lib/
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Identified each subvolume so I could know which ones where mounted as my main filesystem:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[root&amp;#64;localhost ~]# touch /mnt/toplevel/root/stdroot
[root&amp;#64;localhost ~]# touch /mnt/toplevel/fedoraroot/fedoraroot
[root&amp;#64;baley toplevel]# touch fedoraroot/var/fedoravar
[root&amp;#64;baley toplevel]# touch ./var/stdvar
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Updated fstab &lt;em&gt;in the snapshot&lt;/em&gt; (that's in &lt;tt class="docutils literal"&gt;fedoraroot&lt;/tt&gt;) since that what we want to use from now on. To do so, I replaced &lt;tt class="docutils literal"&gt;subvol=root&lt;/tt&gt; by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;subvol=fedoraroot```and&lt;/span&gt; ``subvol=var&lt;/tt&gt; by &lt;tt class="docutils literal"&gt;subvol=fedoraroot/var&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Rebooted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Edited the grub line from the menu before booting from it. I updated the &lt;tt class="docutils literal"&gt;subvol&lt;/tt&gt; parameter of the kernel to be &lt;tt class="docutils literal"&gt;subvol=fedoraroot&lt;/tt&gt;. This way grub mounted the proper subvolume during boot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Checked that everything was correct:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[root&amp;#64;localhost ~]# btrfs subvolume show /
fedoraroot
        Name:                   fedoraroot
        UUID:                   1fc8ffa2-76f5-a343-aae9-4b499073d805
        Parent UUID:            5effda61-179e-9b48-900f-b7ad85d5f9d9
        Received UUID:          -
        Creation time:          2020-02-22 16:14:19 +0100
        Subvolume ID:           268
        Generation:             4554
        Gen at creation:        4447
        Parent ID:              5
        Top level ID:           5
        Flags:                  -
        Snapshot(s):
[root&amp;#64;localhost ~]# ls /fedoraroot
/fedoraroot
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Remounted the top level volume.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Deleted the nested subvolumes: &lt;tt class="docutils literal"&gt;btrfs subvolume delete /mnt/toplevel/root/var/lib/machines/&lt;/tt&gt; (same for portables).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Deleted &lt;tt class="docutils literal"&gt;root&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;var&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
btrfs subvolume delete /mnt/toplevel/root/
btrfs subvolume delete /mnt/toplevel/var/
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Updated grub: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;grub2-mkconfig&lt;/span&gt; &lt;span class="pre"&gt;-o&lt;/span&gt; /boot/grub2/grub.cfg&amp;nbsp;&amp;nbsp; # or /boot/efi/EFI/fedora/grub.cfg if you use EFI&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Checked the generated grub configuration:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[root&amp;#64;localhost ~]# grep -R subvol /boot/grub2/grub.cfg  # The subvolume parameter is correct.
set default_kernelopts=&amp;quot;root=UUID=ce254a08-22e0-481e-b027-498aa059cc1a ro rootflags=subvol=fedoraroot resume=UUID=163891ab-ac20-4e58-8731-306810f99c9c rhgb quiet &amp;quot;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Rebooted. All should still be working.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="installing-tumbleweed"&gt;
&lt;h2&gt;Installing Tumbleweed&lt;/h2&gt;
&lt;p&gt;Just do the normal installation process until you reach the disk setup. Here you'll have to choose &lt;em&gt;Expert partition&lt;/em&gt; and &lt;em&gt;Start with existing partitions&lt;/em&gt;. Then, on the disk that contains you BTRFS volume:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Mount the &lt;tt class="docutils literal"&gt;swap&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Mount the EFI partition under &lt;tt class="docutils literal"&gt;/boot/efi&lt;/tt&gt; (if you use EFI).&lt;/li&gt;
&lt;li&gt;Mount the main BTRFS volume &lt;tt class="docutils literal"&gt;/&lt;/tt&gt; and be sure to skip the formatting of the volume. &lt;tt class="docutils literal"&gt;/boot&lt;/tt&gt; must be under &lt;tt class="docutils literal"&gt;/&lt;/tt&gt; in the BTRFS volume even if you use luks. See below for why.&lt;/li&gt;
&lt;li&gt;Check installation summary: should not remove anything but should create a lot of new subvolume. None should conflict with fedora's.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That should be it. Inspect in the summary the operations done.
You should see that the installer:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Will create all the subvolumes it needs.&lt;/li&gt;
&lt;li&gt;Won't delete anything.&lt;/li&gt;
&lt;li&gt;Will mount the fedora subvolumes. Not a big deal, we will remove that from the fstab once the installation is done.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can launch the installation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="finishing-the-setup-of-tumbleweed"&gt;
&lt;h2&gt;Finishing the setup of Tumbleweed&lt;/h2&gt;
&lt;p&gt;If you use luks, you will have to enter you luks passphrase in Grub with a US keyboard.
You will then have to enter you passphrase normally as part of the boot process.&lt;/p&gt;
&lt;p&gt;By default Tumbleweed will create a subvolume named &lt;tt class="docutils literal"&gt;&amp;#64;&lt;/tt&gt; and create its other subvolumes as subvolumes of it.
Here however, it didn't (I don't know why).
Since I still want a main subvolume for each system (having &lt;tt class="docutils literal"&gt;home&lt;/tt&gt; as a direct subvolume of the top level volume sounds good to me since it is independent of any other system).
So, it's time to move subvolumes again. I won't detail much this time, I think you know the drill (do this from fedora, the directories are in use in Tumbleweed):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mount -t btrfs -o &lt;span class="nv"&gt;subvolid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; /dev/vda3 /mnt/toplevel/
&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/toplevel/
btrfs subvolume list .

&lt;span class="c1"&gt;# Repeat for each subvolume.
&lt;/span&gt;rmdir /mnt/toplevel/&amp;#64;/var/
btrfs subvolume snapshot /mnt/toplevel/var /mnt/toplevel/&amp;#64;

&lt;span class="c1"&gt;# Check. Don't remove subvolume while in use, the deletion will come later.
&lt;/span&gt;btrfs subvolume list /mnt/toplevel
btrfs subvolume list .
&lt;/pre&gt;
&lt;p&gt;Let's edit the fstab.
We are just appending &lt;tt class="docutils literal"&gt;&amp;#64;/&lt;/tt&gt; to each &lt;tt class="docutils literal"&gt;subvol&lt;/tt&gt; arguments like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;subvol=&amp;#64;/var&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;We also need to update &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/boot/grub2/x86_64-efi/load.cfg&lt;/span&gt;&lt;/tt&gt; so grub mounts the correct subvolume during the boot process:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
set btrfs_relative_path='y'
cryptomount -u bf63369674824969a7726fda0cb46537
btrfs-mount-subvol ($root) /boot/grub2/x86_64-efi &amp;#64;/boot/grub2/x86_64-efi
&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;I didn't need this step in my VM and given the content of the file, I think it is specific to luks.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can now reboot. Everything should go well. Boot on the other system if not.&lt;/p&gt;
&lt;p&gt;We can now delete the old subvolumes from the installation:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mount -t btrfs -o &lt;span class="nv"&gt;subvolid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; /dev/vda3 /mnt/toplevel/
&lt;span class="nb"&gt;cd&lt;/span&gt; /mnt/toplevel/
&lt;span class="c1"&gt;# Repeat for each subvolume.
&lt;/span&gt;btrfs subvolume delete ./var
&lt;/pre&gt;
&lt;p&gt;We can also enable snapper now to have snapshot.
It's done automatically during a normal installation but not here (because we did weird things I guess).
We can do this with &lt;tt class="docutils literal"&gt;snapper &lt;span class="pre"&gt;-c&lt;/span&gt; root &lt;span class="pre"&gt;create-config&lt;/span&gt; /&lt;/tt&gt;.
And we are done!&lt;/p&gt;
&lt;div class="admonition warning"&gt;
&lt;p class="first admonition-title"&gt;Avis&lt;/p&gt;
&lt;p class="last"&gt;Fedora uses subvol in &lt;tt class="docutils literal"&gt;grub.cfg&lt;/tt&gt; but not Tumbleweed. Tumbleweed changes the default subvolume of the top level volume. It's not a problem with this setup but if you want to install two systems that do this, you will have to make at least one explicitly use &lt;tt class="docutils literal"&gt;subvol&lt;/tt&gt; everywhere.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="wrapping-up"&gt;
&lt;h2&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;It required a lot of preparation and tests but I'm glad I made it.
I find Tumbleweed fast (faster than fedora at boot and when installing package) and reliable (from what I used until now).
I'll need to do more testing to confirm that (the system is very fresh after all).
I also learned a lot about BTRFS, subvolumes and snapshots along the way.
I still have some issues though:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The nextcloud client ask me to reconnect each time I launch it. It may come from a configuration shared with Fedora. I'll fix this later once I know which system I want to keep.&lt;/li&gt;
&lt;li&gt;The grub menu to choose the kernel (or the snapshot) is sometimes not displayed.&lt;/li&gt;
&lt;li&gt;Grub takes some time to start once the key is entered.&lt;/li&gt;
&lt;li&gt;If I fail to enter my passphrase for grub of the first try, it fails and I have to do a hard reboot.&lt;/li&gt;
&lt;li&gt;I decided to switch from Gnome to KDE and I think I hit a bug with the online accounts that prevent me to setup my gmail account. I'll have to dig into this later (I'll try to update this post if I find the solution). I also spent a lot of time to configure KMail (which has a lot of options by the way).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="bonus"&gt;
&lt;h2&gt;Bonus&lt;/h2&gt;
&lt;div class="section" id="enter-luks-passphrase-only-once"&gt;
&lt;h3&gt;Enter luks passphrase only once&lt;/h3&gt;
&lt;p&gt;If you use luks, you have to enter your luks passphrase twice: once to unlock &lt;tt class="docutils literal"&gt;/boot&lt;/tt&gt; so grub can start the system and then so the system can access the disk.
Sadly, they can't communicate (yet?).&lt;/p&gt;
&lt;p&gt;You could put &lt;tt class="docutils literal"&gt;/boot&lt;/tt&gt; on an unencrypted filesystem (that's what fedora does), but according to &lt;a class="reference external" href="https://forums.opensuse.org/showthread.php/525491-GRUB2-decryption-password-enter-twice"&gt;this thread&lt;/a&gt; you won't be able to boot from a BTRFS snapshot (which is one cool thing Tumbleweed enables by default).&lt;/p&gt;
&lt;p&gt;You can also fellow &lt;a class="reference external" href="https://cryptsetup-team.pages.debian.net/cryptsetup/encrypted-boot.html"&gt;these steps&lt;/a&gt; so you'll only have to enter the passphrase for grub. Check also &lt;a class="reference external" href="https://forums.opensuse.org/showthread.php/525314-How-can-I-insert-a-file-into-the-initramfs"&gt;this link&lt;/a&gt; to update the initramfs in Tumbleweed (don't forget to launch &lt;tt class="docutils literal"&gt;dracut &lt;span class="pre"&gt;--force&lt;/span&gt;&lt;/tt&gt;). For reference, my &lt;tt class="docutils literal"&gt;/etc/dracut.conf&lt;/tt&gt; contains:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# PUT YOUR CONFIG IN separate files
# in /etc/dracut.conf.d named &amp;quot;&amp;lt;name&amp;gt;.conf&amp;quot;
# SEE man dracut.conf(5) for options
install_items+=&amp;quot;/etc/luks-keys/root.key&amp;quot;
&lt;/pre&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;If you need to add many files, separate them with spaces like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;install_items+=&amp;quot;/etc/luks-keys/root.key&lt;/span&gt; &lt;span class="pre"&gt;/etc/luks-keys/swap.key&amp;quot;&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Astuce&lt;/p&gt;
&lt;p class="last"&gt;Don't add &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;key-slot=1&lt;/span&gt;&lt;/tt&gt; immediately, if you did a mistake you will be locked out of the system because luks will try to match the key against this slot. Don't forget to adapt the slot if needed. You may also choose not to add it since I found it doesn't really change the boot time anyway.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="tumbleweed-default-install"&gt;
&lt;h3&gt;Tumbleweed default install&lt;/h3&gt;
&lt;p&gt;For reference:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
localhost:~ # btrfs subvolume list /
ID 256 gen 32 top level 5 path &amp;#64;
ID 258 gen 4192 top level 256 path &amp;#64;/var
ID 259 gen 4125 top level 256 path &amp;#64;/usr/local
ID 260 gen 4192 top level 256 path &amp;#64;/tmp
ID 261 gen 3045 top level 256 path &amp;#64;/srv
ID 262 gen 4166 top level 256 path &amp;#64;/root
ID 263 gen 3620 top level 256 path &amp;#64;/opt
ID 264 gen 4192 top level 256 path &amp;#64;/home
ID 265 gen 26 top level 256 path &amp;#64;/boot/grub2/x86_64-efi
ID 266 gen 3550 top level 256 path &amp;#64;/boot/grub2/i386-pc
ID 267 gen 4118 top level 256 path &amp;#64;/.snapshots
ID 268 gen 4191 top level 267 path &amp;#64;/.snapshots/1/snapshot
ID 274 gen 197 top level 267 path &amp;#64;/.snapshots/2/snapshot
ID 275 gen 262 top level 267 path &amp;#64;/.snapshots/3/snapshot
ID 278 gen 485 top level 267 path &amp;#64;/.snapshots/4/snapshot
ID 282 gen 1614 top level 267 path &amp;#64;/.snapshots/5/snapshot
ID 283 gen 2100 top level 267 path &amp;#64;/.snapshots/6/snapshot
ID 290 gen 3024 top level 267 path &amp;#64;/.snapshots/11/snapshot
ID 291 gen 3066 top level 267 path &amp;#64;/.snapshots/12/snapshot
ID 292 gen 3233 top level 267 path &amp;#64;/.snapshots/13/snapshot
ID 295 gen 3551 top level 267 path &amp;#64;/.snapshots/14/snapshot
ID 296 gen 3593 top level 267 path &amp;#64;/.snapshots/15/snapshot
ID 297 gen 3613 top level 267 path &amp;#64;/.snapshots/16/snapshot
ID 301 gen 3631 top level 267 path &amp;#64;/.snapshots/17/snapshot
ID 305 gen 4005 top level 267 path &amp;#64;/.snapshots/18/snapshot
ID 306 gen 4051 top level 267 path &amp;#64;/.snapshots/19/snapshot
ID 307 gen 4113 top level 267 path &amp;#64;/.snapshots/20/snapshot

localhost:/mnt/toplevel # cat /etc/fstab
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /                       btrfs  defaults                      0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /var                    btrfs  subvol=/&amp;#64;/var                 0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /usr/local              btrfs  subvol=/&amp;#64;/usr/local           0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /tmp                    btrfs  subvol=/&amp;#64;/tmp                 0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /srv                    btrfs  subvol=/&amp;#64;/srv                 0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /root                   btrfs  subvol=/&amp;#64;/root                0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /opt                    btrfs  subvol=/&amp;#64;/opt                 0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /home                   btrfs  subvol=/&amp;#64;/home                0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /boot/grub2/x86_64-efi  btrfs  subvol=/&amp;#64;/boot/grub2/x86_64-efi  0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /boot/grub2/i386-pc     btrfs  subvol=/&amp;#64;/boot/grub2/i386-pc  0  0
UUID=e5a3ef21-d865-4bb6-bd11-6056ff4a60b1  /.snapshots             btrfs  subvol=/&amp;#64;/.snapshots          0  0
UUID=6f2fce23-6460-4d69-9e69-a5b6b5e4456c  swap                    swap   defaults                      0  0
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="Linux"></category><category term="BTRFS"></category></entry><entry><title>Why you probably want to make a SPA</title><link href="//www.jujens.eu/posts/en/2020/Jan/12/why-you-want-make-spa/" rel="alternate"></link><published>2020-01-12T00:00:00+01:00</published><updated>2020-01-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2020-01-12:/posts/en/2020/Jan/12/why-you-want-make-spa/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I created an updated version of this article in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Jun/15/should-you-build-pwa/"&gt;should you build a SPA&lt;/a&gt; which provides a more complete and balanced view on this subject. Please read it instead of this current article.&lt;/p&gt;
&lt;p&gt;I am currently working professionally on a website that is not a SPA. I'd like to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I created an updated version of this article in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Jun/15/should-you-build-pwa/"&gt;should you build a SPA&lt;/a&gt; which provides a more complete and balanced view on this subject. Please read it instead of this current article.&lt;/p&gt;
&lt;p&gt;I am currently working professionally on a website that is not a SPA. I'd like to rely on this experience to explain the pain points I encounter in the hope to convince you to build a SPA from scratch on you next project.&lt;/p&gt;
&lt;p&gt;First, I'll discuss some arguments you may have against SPAs hoping to change you mind:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Habit: you are maybe used to build website with frameworks like &lt;a class="reference external" href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; which, because of the context in which they were created, favors building websites with their template engines and to add JavaScript (most likely with jQuery) only to parts of the site, where you need the page to be dynamic. I think it's the weaker argument against building a SPA: in web development, technologies are changing and evolving and if you keep doing things out of habit, your skills will become irrelevant sooner or later. Note that I am not suggesting you should learn every new shiny thing that appears: it will take you a lot of time and it will never really pay off since the shiny thing will be replaced by something shinier very quickly. What I am saying is that we now have some mature and popular frameworks and libraries to build SPAs. They will stay around and thus are worth learning (you'll find a list near the end of this article). So, my advise is: learn one of them to expand your skill set and make SPAs your new habit!&lt;/li&gt;
&lt;li&gt;You've never done it: I think it is very similar to the habit argument seen above. So I'll just say: it can be learned, others have done it and have shared how they did it. So you should be able to get help to start by reading some articles or books, browsing StackOverflow or by hiring a consultant.&lt;/li&gt;
&lt;li&gt;Too complex for what you are doing: I have to admit these frameworks can be daunting, mostly at first. They come with new concepts, ideas and ways of doing things. And you will be running a full application in the browser of your users which is objectively more complex than just displaying a good old HTML page. I think it can be a very good argument against building a SPA. Depending on your context and current skills, a SPA may not make sense. For instance, you are prototyping or the site you are building is just for internal use or you are building it on your spare time to have fun. But for a website that you build professionally and that will release to the public, I still think you should go for a SPA even if you think you may not need it at first because you probably will need one (keep reading 😉).&lt;/li&gt;
&lt;li&gt;You'll ever have the need: I think you probably will have the need and sooner than you think. For better or worse, users expect more and more dynamic and interactive web pages that respond quickly without page reloads. The more your site will grow, the more you will need dynamic parts: the header to show the user is logged in, some search results to display dynamically, a small dynamic component to improve user experience on a page, a tiny embed app… And these parts probably won't stay isolated: they will have to talk/interact with each other. It will be much easier to do in a SPA: you have a top component or a store to store global information so each sub-components can be updated correctly when one changes. Without, you may need to rely on custom events, global state that you manage yourself, maybe even a page reload or you'll have different technologies you'll have to make interact (let's say jQuery because that's what you started with and ReactJS because you needed it for complex interactions). Note that part of the pain can be mitigated with a global store injected in multiple components. But it will probably end up in a strange mix of technologies.&lt;/li&gt;
&lt;li&gt;Find the skills: If you go for a SPA, you will need to be (or need your colleges to be) proficient in both backend and frontend development. If you already have frontend development skills or frontend developers in your team, then you're fine. If not, there are two different kind of skills you'll need:&lt;ul&gt;
&lt;li&gt;UX/design/HTML/CSS skills: This is to design the page and have something both pretty and usable. Let's face it, you'll need that anyway and you probably already have it (maybe with a contractor). You can make it easier for you by relying on a CSS framework so you don't have to do all the heavy lifting (backend developers tend not to like that anyway and it's harder than it seems). Just get some basic skills to be able to do some adaptations to what the designer gives you. In the end, UX/design is a job on its own and I don't think it is fair to expect this from you (nor to expect you designers to be developers).&lt;/li&gt;
&lt;li&gt;JavaScript skills with a JavaScript framework: Probably the easiest thing to get. The code will be similar to what you are already writing and most backend developers don't really mind writing JS from time to time (mostly modern JS though, not JS for IE though). And since you rely on a framework, it will handle most of the compatibility between browsers for you. Since JavaScript skills are in high demand (even in the backend side with NodeJS), learning these skills is in your interest too. You may stumble on browser specific issues from time to time or have trouble to adapt some CSS code, but you can leverage this with either getting some time to learn, hiring a contractor or a &amp;quot;true&amp;quot; frontend developer (if you can afford it).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;You can use frameworks like ReactJS or Vue.js &lt;a class="footnote-reference" href="#vue-react-framework-or-lib" id="id1"&gt;[1]&lt;/a&gt; to enhance only part of the page, this way you'll have the best of both worlds: a globally static website with dynamic parts only where needed. The problem is that as stated above, as your site grow, you will have more and more of those dynamic parts and they will have to interact which will be way easier to do in a SPA.&lt;/li&gt;
&lt;li&gt;They come with their own set of challenges: True. You will have to organize your code differently and your backend will be more like an API than a &amp;quot;good old website&amp;quot;. But this can be learned. You will also most likely need server side rendering (or SSR for short). It may require some adaptation in your infrastructure but I think it is mature for the big frameworks so it shouldn't really be an issue. You should be able to find many resources about this online for your framework of choice.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, I'll give some arguments about why SPAs are cool and so why you really want to do them:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;If you don't start with a SPA, it will be hard to change later. You will have to redo your whole site: the frontend in a JS framework and part of your backend so it can be used in a API fashion. That's a lot of work you can avoid by doing a SPA first.&lt;/li&gt;
&lt;li&gt;For better or worse, users expect JS and dynamic things. So you will need dynamic components on your site whether you want it or not. I think you should go for the easiest world and make your site dynamic first.&lt;/li&gt;
&lt;li&gt;All the dynamic parts are done in the same technology. You may be tempted to use &lt;a class="reference external" href="https://jquery.com/"&gt;jQuery&lt;/a&gt; to add basic dynamic parts. But as your site will grow, this will likely not suffice or become too complex to manage. So you'll add something like ReactJS or Vue.js. But then you have a weird hybrid and will have to make your jQuery parts work with your framework parts which is more complicated than it sounds and results in a poor developer experience (and once your developers will be used to modern frameworks, I&amp;nbsp;think they won't be pleased to work with ever jQuery again).&lt;/li&gt;
&lt;li&gt;Maintaining two templates: for SEO or user experience to speed up initial page load, you might want to render the dynamic components on the server and cache them before they are rendered in the browser of the user. Since this is traditionally done in your backend templates, you'll have templates for server side rendering in your backend and JavaScript components that will take over in the browser to add dynamism. So you end up duplicating the work. Or to avoid this, you may want to render your application directly on the server. But part of the page will be rendered by your backend templating engine while some elements will be rendered by something else. It is way harder to do correctly than do all the rendering work in one technology.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before concluding, a few word if you are currently in a hybrid site with part of it done in the &amp;quot;good old way&amp;quot; and part of it in a JavaScript framework. No matter why you got there, it's where you are. Converting everything to a SPA will be long, painful and costly. It will look a lot like a rewrite and you should avoid it if possible. Although I favour SPAs and if the developer experience won't be that great in an hybrid website, I think you should avoid the cost and risk associated with a rewrite (even of just the frontend) if possible. Most issues impact you as a developer but can be worked around to still provide a good user experience. My opinion is: use the JavaScript framework everywhere you can, always use it for new work and convert steps by steps the older part of your site as need rises. Look into SSR because you will need it sooner or later. In the end, let your new dynamic parts eat up the older static parts.&lt;/p&gt;
&lt;p&gt;Here's a small list of frameworks (at time of writing in the beginning of 2020) that you may want to look into to build a SPA:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://reactjs.org"&gt;ReactJS&lt;/a&gt;: Maybe the most popular choice right now. While it was initially design to be included in a &amp;quot;static&amp;quot; page to add some dynamism to it, you can build full SPAs with it and even mobile apps. React itself is quite small so you will probably need to add some other libraries to extend its capabilities a bit. React can be added incrementally to you site to add dynamic parts step by step.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://vuejs.org/"&gt;Vue.js&lt;/a&gt;: Another popular option. Very similar to React in principles (small, incremental) with a different approach that you may prefer coming from a &amp;quot;traditional web development&amp;quot; background.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://angular.io/"&gt;Angular&lt;/a&gt;: While the first two are relatively small and can be added incrementally, Angular is a big framework designed to build SPA. I don't think you will be able to enhance an existing static website with it (not easily at least). While its size may be daunting, it is complete and you probably won't need additional libraries with it. Furthermore, its tooling is mature and able to reduce the size of your code to only include the code you actually use to keep the JS you send small. Given its approach, it might be the right choice for you if you come from a Java/.NET background.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://aurelia.io/"&gt;Aurelia&lt;/a&gt;: Not as popular as the other options, but I&amp;nbsp;think it is a sweet spot between the completeness and complexity of Angular and minimalism of React or Vue. Like Angular it is a complete framework designed to build SPA, but it focuses on web standards and tries to get out of your way so you can write standard JavaScript or include standard JavaScript libraries as easily as possible. Which makes it easier to learn and develop with (in my opinion at least).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To conclude, I am now convinced that SPAs are the way to go by default. There may still be use cases for &amp;quot;good old website&amp;quot; but I think the list is small and is getting smaller. Even if SPAs may require you to learn new skills and if they come with their own set of challenges, I think (and I hope I&amp;nbsp;have convinced you) that SPAs will make you life easier in the long run.&lt;/p&gt;
&lt;p&gt;If you have a remark or disagree, please leave a comment below.&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="vue-react-framework-or-lib" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;You may say these are more libraries than frameworks. I agree, but I'll keep calling them frameworks to ease writing since I also want to include SPA frameworks like Angular or Aurelia.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category><category term="Web"></category><category term="Django"></category></entry><entry><title>Writing a PWA with Aurelia</title><link href="//www.jujens.eu/posts/en/2019/Sep/01/aurelia-pwa/" rel="alternate"></link><published>2019-09-01T00:00:00+02:00</published><updated>2019-09-01T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2019-09-01:/posts/en/2019/Sep/01/aurelia-pwa/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#pwa-basics" id="id1"&gt;PWA basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#the-app" id="id2"&gt;The App&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#manifest-json" id="id3"&gt;manifest.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#serviceworker" id="id4"&gt;ServiceWorker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id5"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#resources" id="id6"&gt;Resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;I feel like Progressive Web Application (PWA for short) are a more and more popular way to build mobile apps.
That's understandable since you can use the same technology you use to build a SPA to build one!
So you …&lt;/p&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#pwa-basics" id="id1"&gt;PWA basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#the-app" id="id2"&gt;The App&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#manifest-json" id="id3"&gt;manifest.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#serviceworker" id="id4"&gt;ServiceWorker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id5"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#resources" id="id6"&gt;Resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;I feel like Progressive Web Application (PWA for short) are a more and more popular way to build mobile apps.
That's understandable since you can use the same technology you use to build a SPA to build one!
So you stay in known grounds, can use your usual web browser to develop and test the app.
And, unlike hybrid apps, you also enhance your standard SPA!
In this article, I'll explain how I build a PWA named &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss"&gt;aurss&lt;/a&gt; with the &lt;a class="reference external" href="https://aurelia.io/"&gt;Aurelia framework&lt;/a&gt;.
I'll start by explaining what PWAs are and some specific tech you must use to make them work. Then I'll explain how to build one with Aurelia.&lt;/p&gt;
&lt;div class="section" id="pwa-basics"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;PWA basics&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Simply put, PWAs are &amp;quot;installed&amp;quot; web pages: when you browse on a website that is a PWA, you will be prompted to install it.
If you accept, you will see the icon of the APP on your home screen (like any other app) and if you press this icon, the PWA will launch in full screen mode just like a native app.
But you didn't go to the app store to install it.&lt;/p&gt;
&lt;p&gt;As a developer, building a PWA means:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Your users don't have to install it: they can use the app directly on the website without installing anything and you'll still be able to provide them advanced features like caching.&lt;/li&gt;
&lt;li&gt;You will have more control on when you can update it: no need to submit it to the app store and wait for validation. Just push files to you server. The update will occur the next time your users reopen the app.&lt;/li&gt;
&lt;li&gt;You are not bound by the rules of any app stores.&lt;/li&gt;
&lt;li&gt;The app will work on any device with a recent browser.
Chrome has the best support for PWAs right now, Firefox is quite good but Safari support can be an issue (even if it's getting better, see &lt;a class="reference external" href="https://medium.com/&amp;#64;firt/whats-new-on-ios-12-2-for-progressive-web-apps-75c348f8e945"&gt;this article for instance&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;The app can be progressively enhanced (eg by adding better offline support or better caching).&lt;/li&gt;
&lt;li&gt;You show notifications the user with the &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/notification"&gt;Notification API&lt;/a&gt; and  the &lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/Push_API"&gt;Push API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can access &lt;em&gt;some&lt;/em&gt; native features (like the camera or the microphone).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are the basic components needed to make a PWA:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;manifest.json&lt;/tt&gt;: it's a JSON file describing how the app must be displayed and installed. You'll use it to specify the name, icon, orientation and some display properties of your app. See &lt;a class="reference external" href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json"&gt;here&lt;/a&gt; for more details. &lt;em&gt;It is required to make your app a PWA.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;ServiceWorker&lt;/tt&gt; (SW for short): it behaves like a proxy server between your app and the network. It will keep working even when the tab is closed. So it will allow you to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Have caching and offline support.&lt;/li&gt;
&lt;li&gt;Sync things in the background.&lt;/li&gt;
&lt;li&gt;Subscribe to notifications of the Push API and display them to users.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please note that:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;It only works over HTTPS (except for localhost).&lt;/li&gt;
&lt;li&gt;It cannot access the DOM.&lt;/li&gt;
&lt;li&gt;It may apply to all or only part of the pages.&lt;/li&gt;
&lt;li&gt;It must be registered to have an effect.&lt;/li&gt;
&lt;li&gt;It will only get updated if its content changed and after the tab is closed and reopen (unless you use the dev tools and force it to reload on change).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/Service_Worker_API"&gt;here&lt;/a&gt; for more. &lt;em&gt;It is required to make your app a PWA.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt;: where you put data to exchange with the SW (SW cannot access &lt;tt class="docutils literal"&gt;localStorage&lt;/tt&gt;). See &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API"&gt;here&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Many other APIs I'll just list here so you know what you can do:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/notification"&gt;Notification API&lt;/a&gt; to display notification to the user.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/Push_API"&gt;Push API&lt;/a&gt; to receive messages from a server.&lt;/li&gt;
&lt;li&gt;Many more: geolocation, camera access, …&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="the-app"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;The App&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we've seen what the basic components are, let's see how to do this with Aurelia.&lt;/p&gt;
&lt;p&gt;In a nutshell, you want to build a normal app while paying attention to some details, relating with the SW: it will rely on &lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt; for storage, on the fetch API for network (luckily that's what the Aurelia HTTP client is using), all its APIs are promise based and &lt;em&gt;it will be reinstalled only when it changes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I assume you are familiar with Aurelia so I won't explain Aurelia specific things (since they don't exist, I just build a standard app using the framework) and focus on PWA stuff. Anything I explain here is applicable with a basic app created by the CLI (if possible use webpack since this article will be easier to follow if you do).&lt;/p&gt;
&lt;p&gt;So to make your app a PWA, you will have to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Add the &lt;tt class="docutils literal"&gt;manifest.json&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Add the service worker.&lt;/li&gt;
&lt;li&gt;Check with &lt;a class="reference external" href="https://developers.google.com/web/tools/lighthouse/"&gt;lighthouse&lt;/a&gt; that the app is installable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can then add other capabilities if needed.&lt;/p&gt;
&lt;div class="section" id="manifest-json"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;manifest.json&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once you've build the app, you can add the &lt;tt class="docutils literal"&gt;manifest.json&lt;/tt&gt; file. To do so add in your &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;index.ejs&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;manifest&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/manifest.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Then in the &lt;tt class="docutils literal"&gt;static/&lt;/tt&gt; folder (if you are not using webpack as configured by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-cli&lt;/span&gt;&lt;/tt&gt;, you may need to adapt this, the goal is to have this file in the root of the build files next to the &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt; file), you can create the &lt;tt class="docutils literal"&gt;manifest.json&lt;/tt&gt; file. Below is an example, you can adapt it to your needs. It also has more properties, see &lt;a class="reference external" href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json"&gt;the documentation&lt;/a&gt; to view all its possibilities.&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurss – RSS reader&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;short_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurss&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;start_url&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;scope&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;display&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;standalone&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;background_color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;#FFF&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;theme_color&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;#493174&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;RSS reader for TTRSS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;dir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ltr&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;lang&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;en-US&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;orientation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;portrait-primary&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;icons&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/icons/aurss.96x96.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;image/png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;sizes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;96x96&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;src&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/icons/aurss.512x512.png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;image/png&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;sizes&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;512x512&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="serviceworker"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;ServiceWorker&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Then, include the service worker:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Create a file named &lt;tt class="docutils literal"&gt;sw.js&lt;/tt&gt; in your &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; folder. Leave it empty for now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Register the worker in the &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt; with:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'serviceWorker'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Service worker is registered'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;registrationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s1"&gt;'Service worker failed to register'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;registrationError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Service worker is not available in this browser.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Make sure it will be copied when you build the application next to the &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt;. For instance, with webpack, you can use &lt;a class="reference external" href="https://www.npmjs.com/package/serviceworker-webpack-plugin"&gt;this plugin&lt;/a&gt; (which will also be handy later for caching so I recommend that you use it or something similar).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;Even you are using TypeScript, I suggest you rely on plain JavaScript for the SW file. It will be much easier to write and you won't have to worry about transpilation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Astuce&lt;/p&gt;
&lt;p class="last"&gt;If you are using Chrome, the &lt;em&gt;Application&lt;/em&gt; tab of the dev tools is really useful. It will show you information about the manifest file, the service worker and the used storage.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Astuce&lt;/p&gt;
&lt;p class="last"&gt;ES6 imports won't work with SW, you must use something like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;importScripts('/src/js/idb.js');&lt;/span&gt;&lt;/tt&gt; to import things.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now the SW is bootstrapped, we can start to use it to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Cache the shell of the app (ie the files it needs to work) and provide offline support. This is done once the SW is installed, so when the &lt;tt class="docutils literal"&gt;installed&lt;/tt&gt; event has been fired (&lt;tt class="docutils literal"&gt;self&lt;/tt&gt; represent the SW instance):&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// Name of our static cache.
&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;staticCachePrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'static'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Update this each time you app shell changes.
// This way, the SW will have changed and get reinstalled
// allowing for the new files to be cached.
&lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;staticCacheName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;staticCachePrefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'install'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Installing SW version:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;VERSION&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// waitUntil is there to make the sure SW is neither paused nor stopped
&lt;/span&gt;    &lt;span class="c1"&gt;// while we expect it to do some work until the promise we passed to it completes.
&lt;/span&gt;    &lt;span class="c1"&gt;// See: https://stackoverflow.com/a/37906330
&lt;/span&gt;    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;staticCacheName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Caching app shell'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="c1"&gt;// serviceWorkerOption comes from serviceworker-webpack-plugin.
&lt;/span&gt;                &lt;span class="c1"&gt;// Adapt if needed.
&lt;/span&gt;                &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serviceWorkerOption&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can then use in your &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt; file, in the &lt;tt class="docutils literal"&gt;constructor&lt;/tt&gt;, something like the code below to display notification to the user about online/offline status:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onOffline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isOffline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onOnline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isOnline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onLine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isOffline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isOnline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'offline'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onOffline&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'online'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onOnline&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Catch network requests, for instance to implement dynamic caching.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fetch'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Let the browser do its default thing
&lt;/span&gt;    &lt;span class="c1"&gt;// for non-GET requests.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'GET'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;When offline, you can store data in &lt;tt class="docutils literal"&gt;indexDB&lt;/tt&gt; to send it as soon as the browser gets online again. To do this, you must listen to the &lt;tt class="docutils literal"&gt;sync&lt;/tt&gt; event in the SW. You can take inspiration from &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/master/src/sw.js#L50"&gt;this code&lt;/a&gt; for the SW part and from &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/master/src/utils/sync.ts"&gt;these utility functions&lt;/a&gt; (see a usage &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/master/src/services/backends/ttrss.ts#L275"&gt;here&lt;/a&gt;) to achieve this.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p class="last"&gt;There are many caching strategies: with network fallback, cache only, network only, network with cache fallback, cache then network. I won't detail them here. Search on the internet if needed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="admonition note"&gt;
&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Don't forget to clean the cache from time to time. This can be done with:&lt;/p&gt;
&lt;pre class="code javascript last literal-block"&gt;
&lt;span class="nx"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'activate'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Cleaning old cache shell'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;keylist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nx"&gt;keylist&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;staticCacheName&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;staticCachePrefix&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Finally, you should test you app with lighthouse to check it actually is a PWA.
The tool will also check for performance which is a good thing.
In the Chrome dev tools, go to the &lt;em&gt;Audit&lt;/em&gt; tab, verify that &lt;em&gt;Progressive Web App&lt;/em&gt; is checked under the audit section and run the audit.
The report should tell you that you have indeed created a PWA (and if not, what you are missing).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To sum up:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;PWAs are not tied to any framework. You can make a PWA without one or add PWA capabilities to a SPA written with any framework.&lt;/li&gt;
&lt;li&gt;They are quite fast to develop and allow for good code re-use because you are not making an app distinct from you main web site.&lt;/li&gt;
&lt;li&gt;You don't have to learn many new technologies, most of the things you will do will be standard we development.&lt;/li&gt;
&lt;li&gt;You can progressively enhance an app with PWA capabilities.&lt;/li&gt;
&lt;li&gt;Pay attention to what they support and what they don't before starting and to iOS support.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="resources"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Resources&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;My test application: &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss"&gt;aurss&lt;/a&gt; It's MIT licensed so you can re-use it. Don't hesitate to ask me questions in the comment or in Gitlab.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.udemy.com/course/progressive-web-app-pwa-the-complete-guide/"&gt;A course I took (I highly recommand it)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Aurelia"></category><category term="JavaScript"></category><category term="TypeScript"></category><category term="Aurelia"></category><category term="Mobile"></category><category term="PWA"></category></entry><entry><title>Some thoughts on Aurelia Store</title><link href="//www.jujens.eu/posts/en/2019/Aug/24/aurelia-store/" rel="alternate"></link><published>2019-08-24T00:00:00+02:00</published><updated>2019-08-24T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2019-08-24:/posts/en/2019/Aug/24/aurelia-store/</id><summary type="html">&lt;p&gt;On my spare time, I am developing a &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/arena-of-titans"&gt;board game&lt;/a&gt; that uses &lt;a class="reference external" href="https://aurelia.io"&gt;the Aurelia framework&lt;/a&gt;.
I currently manage the state in a service without any dedicated state management solutions (like RxJS, Aurelia store, Redux, …).
And I feel I am reaching to the limit of what I can do with it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;On my spare time, I am developing a &lt;a class="reference external" href="https://gitlab.com/arenaoftitans/arena-of-titans"&gt;board game&lt;/a&gt; that uses &lt;a class="reference external" href="https://aurelia.io"&gt;the Aurelia framework&lt;/a&gt;.
I currently manage the state in a service without any dedicated state management solutions (like RxJS, Aurelia store, Redux, …).
And I feel I am reaching to the limit of what I can do with it and feel the need for a dedicated solution. So I decided to give &lt;a class="reference external" href="https://github.com/aurelia/store/"&gt;aurelia-store&lt;/a&gt; the official plugin for state management for the framework.
I did so in at test project: &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss"&gt;aurss&lt;/a&gt; a small app to list rss feeds.&lt;/p&gt;
&lt;p&gt;First, let me explain a bit why we would need a store: in Aurelia, you can use services (ie instances of a object) that are injected into your components.
You can use them for actions (eg interaction with an external API) and to store data.
If you app is big, you will end up with many services. You'll have to keep them all in sync (maybe with observers or the event aggregator) and make sure your component are correctly updated.&lt;/p&gt;
&lt;p&gt;It turns out this approach can be quite tricky and that's why solutions like Redux (from the React world) or VueX for Vue.js and of course Aurelia store have emerged: to help you manage the state in a single place so you don't have to do the hard work of keeping everything in sync.
Instead of having multiple services, you have one store, you rely on functions to change its state and the store &amp;quot;notifies&amp;quot; your components that something changed and that they must be updated.
It also comes with some nice features like easy persistence and recovery from local storage and time travel.&lt;/p&gt;
&lt;p&gt;Aurelia store more specifically is a plugin for Aurelia to help you use this pattern with the Aurelia framework.
It's based on &lt;a class="reference external" href="http://reactivex.io/rxjs/"&gt;RxJS&lt;/a&gt; a popular library for event programming.
The idea of RxJS is register actions to do when a given event occurs as specified by the observer pattern, ie do something like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fromEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'click'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'clicked!'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;sendEventToAnalytics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I'll let you see the doc of RxJS to learn more about that.&lt;/p&gt;
&lt;p&gt;What's very interesting about Aurelia store is that while based on RxJS (and its full power), it remains easy to use at first: you don't need to know RxJS to start and don't need much knowledge to do even quite advanced things.
Please read &lt;a class="reference external" href="https://aurelia.io/docs/plugins/store#introduction"&gt;the introduction to Aurelia store&lt;/a&gt; to have a more detailed explanation about why the plugin exists and its relationship with RxJS.&lt;/p&gt;
&lt;p&gt;Let's see briefly how to use it (I assume you are already familiar with Aurelia, if not, the official documentation will give you more details on how to integrate it in your app):&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;In your &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; file, you must enable the plugin and define an initial state:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-store'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Inject the &lt;tt class="docutils literal"&gt;Store&lt;/tt&gt; in your components:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-framework'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-store'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;&amp;#64;&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Listen to events with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// `this.state` will receive a new value each time the state is updated.
// This way, the component will re-render.
&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Dispatch actions to update the state:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Don't mutate the state directly, create a new one. See the doc for why.
&lt;/span&gt;    &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{..&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;players&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addPlayer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addPlayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Player &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="admonition tip"&gt;
&lt;p class="first admonition-title"&gt;Astuce&lt;/p&gt;
&lt;p class="last"&gt;Don't forget to dispose of subscription with &lt;tt class="docutils literal"&gt;this.subscription.unsubscribe&lt;/tt&gt;. See &lt;a class="reference external" href="https://aurelia.io/docs/plugins/store#subscribing-to-the-stream-of-states"&gt;the doc&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I must say the experience of using Aurelia store is very pleasant: the plugin is easy to integrate, it works well, it's not hard to understand, it seems to play nice with RxJS if you need some advance features (for instance to register to updates to part of the state or to get only the first change).&lt;/p&gt;
&lt;p&gt;If I compare this to Redux which is the other state management solution I used, I think that using directly functions when we dispatch actions is a very good idea:
instead of having actions and reducers like in Redux, you only have one concept to achieve the same result.
It's also way easier to get started and is easier to understand (each time I have to touch a Redux code base, I have to re-understand how it works and what the link between actions and reducers is).&lt;/p&gt;
&lt;p&gt;The fact that the plugin hides the complexity of RxJS is also a really good thing. By comparison with Angular (from the tutorial I made at least) where RxJS is fully exposed, it really simplifies the development and startup.&lt;/p&gt;
&lt;p&gt;So I am really pleased with the plugin, what I can do with it and the overall developer experience it provides. There are some small gotchas though:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Don't forget to register your actions. You may forget at first. But the store will provide an helpful error message if you forget so it's not the end of the world.&lt;/li&gt;
&lt;li&gt;Pay attention to async actions: unlike other solutions, the Aurelia store allows you to do something like this: &lt;tt class="docutils literal"&gt;await this.store.dispatch(costlyApiCall)&lt;/tt&gt;.
If you do this, your app will freeze until the API call is done which is not what you want (and may not be noticeable locally if your API is on your machine).
So for expensive async operations, split the actions in two: one to do the call and one to update the store when the call is done.
To view an example of this, look at &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/master/src/store/rss-backends-actions.ts#L30"&gt;fetchArticles&lt;/a&gt; and &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/master/src/store/rss-backends-actions.ts#L40"&gt;receivedArticles&lt;/a&gt; from my test app.
But if you know your async actions will resolve fast (querying &lt;a class="reference external" href="https://developer.mozilla.org/fr/docs/Web/API/API_IndexedDB"&gt;IndexDB&lt;/a&gt; for instance), this shouldn't be an issue.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/immerjs/immer"&gt;Immer.js&lt;/a&gt; (useful to ease the writing of state mutation) doesn't work with the plugin out of the box yet (see &lt;a class="reference external" href="https://discourse.aurelia.io/t/aurelia-store-immerjs-and-objects/2601"&gt;this discussion&lt;/a&gt; which also gives a possible solution and &lt;a class="reference external" href="https://github.com/immerjs/immer/issues/392"&gt;this issue&lt;/a&gt;).
Maybe alternative solutions work (like &lt;a class="reference external" href="https://github.com/immutable-js/immutable-js"&gt;immutable.js&lt;/a&gt;) but I haven't tried them.
Update of 2020-08-09: it is now possible, see &lt;a class="reference external" href="//www.jujens.eu/posts/en/2020/Aug/09/aurelia-store-immerjs/"&gt;this update&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further readings:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://aurelia.io/docs/plugins/store#getting-started"&gt;The documentation of the plugin&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For a small project using the store, you can view my test project &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss"&gt;aurss&lt;/a&gt;.
It's a small but usable RSS feed reader which I may improve in the future.
It expects to connect to a &lt;a class="reference external" href="https://tt-rss.org/"&gt;TTRSS&lt;/a&gt; backend.
You can use it  &lt;a class="reference external" href="https://aurss.jujens.eu/#/login"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Several articles by Dwayne Charrington an Aurelia Team member:&lt;ul&gt;
&lt;li&gt;&lt;a class="reference external" href="https://ilikekillnerds.com/2019/08/when-to-use-state-management-in-front-end-applications/"&gt;When To Use State Management In Front-end Applications?&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://ilikekillnerds.com/2019/07/working-with-an-api-in-aurelia-store/"&gt;Working With An API In Aurelia Store&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;His book &lt;a class="reference external" href="https://leanpub.com/mastering-aurelia-store"&gt;Mastering Aurelia Store&lt;/a&gt; (still in progress when I write this).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Aurelia"></category><category term="JavaScript"></category><category term="TypeScript"></category><category term="Aurelia"></category><category term="RxJS"></category></entry><entry><title>Issues while writing tests for a component using i18n</title><link href="//www.jujens.eu/posts/en/2019/Aug/04/i18n-tests-issues/" rel="alternate"></link><published>2019-08-04T00:00:00+02:00</published><updated>2019-08-04T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2019-08-04:/posts/en/2019/Aug/04/i18n-tests-issues/</id><summary type="html">&lt;p&gt;Some time ago, I wanted to add some tests (behavior and render) on an Aurelia component that uses the &lt;a class="reference external" href="https://github.com/aurelia/i18n"&gt;i18n plugin&lt;/a&gt; and more precisely the &lt;tt class="docutils literal"&gt;df&lt;/tt&gt; attribute in the view to display a localized date.&lt;/p&gt;
&lt;p&gt;Since it was a while back (I wanted to write it earlier but couldn't), my …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Some time ago, I wanted to add some tests (behavior and render) on an Aurelia component that uses the &lt;a class="reference external" href="https://github.com/aurelia/i18n"&gt;i18n plugin&lt;/a&gt; and more precisely the &lt;tt class="docutils literal"&gt;df&lt;/tt&gt; attribute in the view to display a localized date.&lt;/p&gt;
&lt;p&gt;Since it was a while back (I wanted to write it earlier but couldn't), my memory may not completely accurate. I hope it can help you nonetheless. If you have questions, please post a comment.&lt;/p&gt;
&lt;p&gt;My component is pretty basic: it takes some bindable as inputs, define a time format to format the date correctly, has 3 methods to add custom behavior and that's it. You can view the model &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/4ae68e3d1c55e441df72804620df7fa06d1e35c7/src/resources/elements/aurss-article.ts"&gt;here&lt;/a&gt; and the view &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss/blob/4ae68e3d1c55e441df72804620df7fa06d1e35c7/src/resources/elements/aurss-article.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also note I am using TypeScript, Webpack and Jest. If you use different tooling, you may need to adapt the example a bit.&lt;/p&gt;
&lt;p&gt;In my test, I setup my component like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StageComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withResources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PLATFORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../../src/resources/elements/aurss-article'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`
    &amp;lt;aurss-article
        value.bind=&amp;quot;article&amp;quot;
        mark-article-as-read.bind=&amp;quot;markArticleAsRead&amp;quot;
        mark-article-as-unread.bind=&amp;quot;markArticleAsUnread&amp;quot;
        open-article.bind=&amp;quot;openArticle&amp;quot;
    &amp;gt;&amp;lt;/aurss-article&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;boundTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// bootstrap comes from aurelia-bootstrapper&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I got this error when running the tests: &lt;tt class="docutils literal"&gt;Error: No ValueConverter named &amp;quot;df&amp;quot; was found!&lt;/tt&gt;. I then tried to register the component with:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StageComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withResources&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;PLATFORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../../src/resources/elements/aurss-article'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;PLATFORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-i18n'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;But all I got was: &lt;tt class="docutils literal"&gt;Error: Error invoking RelativeTime. Check the inner error for details.&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;After reading tests in the plugin repo and &lt;a class="reference external" href="https://kabaehr.de/blog/aurelia-advanced-i18n/"&gt;this article&lt;/a&gt; (which solves a similar problem but the proposed solution didn't work for me), here is how I nailed it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;I created an &lt;tt class="docutils literal"&gt;test/helpers.ts&lt;/tt&gt; file with the code below. Its purpose is to bootstrap the i18n plugin (it resembles what you do in &lt;tt class="docutils literal"&gt;main.ts&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Aurelia&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PLATFORM&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-framework'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-i18n'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prepareI18nComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Aurelia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;standardConfiguration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PLATFORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-i18n'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aliases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'i18n'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

                &lt;span class="c1"&gt;// register backend plugin
&lt;/span&gt;                &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Backend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
                &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="nx"&gt;translation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                                &lt;span class="nx"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="p"&gt;},&lt;/span&gt;
                        &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="nx"&gt;skipTranslationOnMissingKey&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;};&lt;/span&gt;

                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aliases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;loadPath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'./locales/{{lng}}/{{ns}}.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;defaultNS&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'translation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;fallbackLng&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="nx"&gt;interpolation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'{{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'}}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="nx"&gt;lng&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;In the &lt;tt class="docutils literal"&gt;beforeEach&lt;/tt&gt; function, I now setup the component like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;viewModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createArticle&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;markArticleAsRead&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;markArticleAsUnread&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;openArticle&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StageComponent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withResources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PLATFORM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moduleName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../../src/resources/elements/aurss-article'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`
        &amp;lt;aurss-article
            value.bind=&amp;quot;article&amp;quot;
            mark-article-as-read.bind=&amp;quot;markArticleAsRead&amp;quot;
            mark-article-as-unread.bind=&amp;quot;markArticleAsUnread&amp;quot;
            open-article.bind=&amp;quot;openArticle&amp;quot;
        &amp;gt;&amp;lt;/aurss-article&amp;gt;
        `&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;boundTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;prepareI18nComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Bootstrap i18n
&lt;/span&gt;
    &lt;span class="nx"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;I also configured jest to load a file name &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;test/jest-pretest.ts&lt;/span&gt;&lt;/tt&gt; before it executes the tests suite by adding, under the &lt;tt class="docutils literal"&gt;jest&lt;/tt&gt; section of my &lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt; file:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="s2"&gt;&amp;quot;setupFiles&amp;quot;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;&amp;lt;rootDir&amp;gt;/test/jest-pretest.ts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;jest-localstorage-mock&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This file contains:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-loader-nodejs'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;globalize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-pal-nodejs'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-polyfills'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;IntlPolyfill&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'intl'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;relativeToDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'unit'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;globalize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;global&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;navigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="nx"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IntlPolyfill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DateTimeFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IntlPolyfill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IntlPolyfill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DateTimeFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IntlPolyfill&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It is meant to be sure the &lt;tt class="docutils literal"&gt;Intl&lt;/tt&gt; API used by the plugin is correctly defined during the tests.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it! You can also take a look at the full project code in gitlab if you need more details: &lt;a class="reference external" href="https://gitlab.com/Jenselme/aurss"&gt;https://gitlab.com/Jenselme/aurss&lt;/a&gt;&lt;/p&gt;
</content><category term="Aurelia"></category><category term="JavaScript"></category><category term="TypeScript"></category><category term="Aurelia"></category><category term="i18N"></category></entry><entry><title>Extract translations from your Aurelia app</title><link href="//www.jujens.eu/posts/en/2019/Aug/03/extract-translations/" rel="alternate"></link><published>2019-08-03T00:00:00+02:00</published><updated>2019-08-03T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2019-08-03:/posts/en/2019/Aug/03/extract-translations/</id><summary type="html">&lt;p&gt;If you use Aurelia with the &lt;a class="reference external" href="https://github.com/aurelia/i18n"&gt;i18n plugin&lt;/a&gt;, you will have to maintain JSON files that will map a translation key to an actual translation. Manually editing the file to add/remove keys can be tedious.&lt;/p&gt;
&lt;p&gt;Luckily, keys can be extracted automatically thanks to &lt;a class="reference external" href="https://github.com/i18next/i18next-scanner"&gt;i18next-scanner&lt;/a&gt;.  It can extract translation keys …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you use Aurelia with the &lt;a class="reference external" href="https://github.com/aurelia/i18n"&gt;i18n plugin&lt;/a&gt;, you will have to maintain JSON files that will map a translation key to an actual translation. Manually editing the file to add/remove keys can be tedious.&lt;/p&gt;
&lt;p&gt;Luckily, keys can be extracted automatically thanks to &lt;a class="reference external" href="https://github.com/i18next/i18next-scanner"&gt;i18next-scanner&lt;/a&gt;.  It can extract translation keys  from JavaScript, TypeScript and HTML files.&lt;/p&gt;
&lt;p&gt;To do this:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Install &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;i18next-scanner&lt;/span&gt;&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;--save-dev&lt;/span&gt; &lt;span class="pre"&gt;i18next-scanner&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;yarn add &lt;span class="pre"&gt;-D&lt;/span&gt; &lt;span class="pre"&gt;i18next-scanner&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Add the code below in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;i18next-scanner.config.js&lt;/span&gt;&lt;/tt&gt; file at the root of your project.&lt;/li&gt;
&lt;li&gt;Run &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;./node_modules/.bin/i18next-scanner&lt;/span&gt; &lt;span class="pre"&gt;src/**/*.{js,ts,html}&lt;/span&gt;&lt;/tt&gt; to extract the translations. They will be under &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;src/locales/{{lng}}/translation.json&lt;/span&gt;&lt;/tt&gt;. Keys to be translated will have the value &lt;tt class="docutils literal"&gt;__STRING_NOT_TRANSLATED__&lt;/tt&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The extraction supports the following patterns:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;In code files: it will extract keys directly from &lt;tt class="docutils literal"&gt;i18next&lt;/tt&gt; (usage like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;i18next.t('my-key')&lt;/span&gt;&lt;/tt&gt;) and from the injected &lt;tt class="docutils literal"&gt;I18N&lt;/tt&gt; service (ie if you use it like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;this.i18n.tr('my-key')&lt;/span&gt;&lt;/tt&gt;).&lt;/li&gt;
&lt;li&gt;In HMTL files:&lt;ul&gt;
&lt;li&gt;With the following attributes: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;data-i18n&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;data-t&lt;/span&gt;&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;t&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;i18n&lt;/tt&gt; (usage like this &lt;tt class="docutils literal"&gt;&amp;lt;p &lt;span class="pre"&gt;t='my-key'&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/tt&gt;).&lt;/li&gt;
&lt;li&gt;With the following behaviors: &lt;tt class="docutils literal"&gt;t&lt;/tt&gt; (usage &lt;tt class="docutils literal"&gt;${ 'myKey' | t }&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;${ 'myKey' &amp;amp; t }&lt;/tt&gt; – the whitespace is not important).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If this doesn't exactly work for your use cases, please adapt the code below and ask a question in the comments if needed.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fs'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'path'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typescript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;typescript&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;    &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;        &lt;span class="s1"&gt;'src/**/*.{ts}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'./'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;    &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;        &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;        &lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;            &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'i18next.t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'i18n.t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'this.i18n.tr'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;            &lt;span class="nx"&gt;extensions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'.js'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;        &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;        &lt;span class="nx"&gt;lngs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;        &lt;span class="nx"&gt;ns&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;            &lt;span class="s1"&gt;'translation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;        &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;        &lt;span class="nx"&gt;defaultLng&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;        &lt;span class="nx"&gt;defaultNs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'translation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;        &lt;span class="nx"&gt;defaultValue&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'__STRING_NOT_TRANSLATED__'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;        &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;            &lt;span class="nx"&gt;loadPath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'src/locales/{{lng}}/{{ns}}.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;            &lt;span class="nx"&gt;savePath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'src/locales/{{lng}}/{{ns}}.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;            &lt;span class="nx"&gt;jsonIndent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;            &lt;span class="nx"&gt;lineEnding&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;        &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;        &lt;span class="nx"&gt;nsSeparator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// namespace separator
&lt;/span&gt;&lt;span class="ln"&gt;30 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;        &lt;span class="nx"&gt;keySeparator&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// key separator
&lt;/span&gt;&lt;span class="ln"&gt;31 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;        &lt;span class="nx"&gt;interpolation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;            &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'{{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;            &lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'}}'&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;        &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;        &lt;span class="nx"&gt;removeUnusedKeys&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;    &lt;span class="nx"&gt;transform&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;customTransform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;enc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;        &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;        &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;enc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'.ts'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;            &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;outputText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;typescript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transpileModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;                &lt;span class="nx"&gt;compilerOptions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;45 &lt;/span&gt;                    &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'es2018'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;46 &lt;/span&gt;                &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;                &lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;            &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;49 &lt;/span&gt;
&lt;span class="ln"&gt;50 &lt;/span&gt;            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parseFuncFromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'i18next.t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'i18next.tr'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'this.i18n.tr'&lt;/span&gt;&lt;span class="p"&gt;]});&lt;/span&gt;
&lt;span class="ln"&gt;51 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'.html'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;52 &lt;/span&gt;            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;
&lt;span class="ln"&gt;53 &lt;/span&gt;                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parseAttrFromString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'data-i18n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'data-t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'i18n'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;54 &lt;/span&gt;
&lt;span class="ln"&gt;55 &lt;/span&gt;            &lt;span class="c1"&gt;// We extra behaviours `${ 'myKey' | t }` and `${ 'myKey' &amp;amp; t }` from the file.
&lt;/span&gt;&lt;span class="ln"&gt;56 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;            &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;extractBehaviours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/\${ *'([a-zA-Z0-9]+)' *[&amp;amp;|] *t *}/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;57 &lt;/span&gt;            &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;58 &lt;/span&gt;            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;59 &lt;/span&gt;            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;60 &lt;/span&gt;                &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;extractBehaviours&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;61 &lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;62 &lt;/span&gt;                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;63 &lt;/span&gt;                &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;64 &lt;/span&gt;                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="ln"&gt;65 &lt;/span&gt;            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;66 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;67 &lt;/span&gt;
&lt;span class="ln"&gt;68 &lt;/span&gt;        &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;69 &lt;/span&gt;    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;70 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can also view the code in gitlab: &lt;a class="reference external" href="https://gitlab.com/snippets/1881948"&gt;https://gitlab.com/snippets/1881948&lt;/a&gt;&lt;/p&gt;
&lt;p class="warning"&gt;
Because of the &lt;code&gt;removeUnusedKeys: true&lt;/code&gt; options, keys that are not found will be removed from the JSON files. If you don't want this behavior, switch this option to &lt;code&gt;false&lt;/code&gt;.
&lt;/p&gt;&lt;p class="note"&gt;
It is compatible with Javascript and Typescript. If you don't use Typescript, remove the line &lt;code&gt;const typescript = require("typescript");&lt;/code&gt; to avoid issues at import.
&lt;/p&gt;</content><category term="Aurelia"></category><category term="JavaScript"></category><category term="TypeScript"></category><category term="Aurelia"></category><category term="i18N"></category></entry><entry><title>CSS tips</title><link href="//www.jujens.eu/posts/en/2019/Mar/10/css/" rel="alternate"></link><published>2019-03-10T00:00:00+01:00</published><updated>2019-03-10T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2019-03-10:/posts/en/2019/Mar/10/css/</id><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#apply-style-to-ie11-only" id="id1"&gt;Apply style to IE11 only&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="apply-style-to-ie11-only"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Apply style to IE11 only&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Put the style in this media query:&lt;/p&gt;
&lt;pre class="code CSS literal-block"&gt;
&lt;span class="p"&gt;&amp;#64;&lt;/span&gt;&lt;span class="k"&gt;media&lt;/span&gt; &lt;span class="nt"&gt;screen&lt;/span&gt; &lt;span class="nt"&gt;and&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-ms-high-contrast&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;active&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-ms-high-contrast&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nt"&gt;Put&lt;/span&gt; &lt;span class="nt"&gt;CSS&lt;/span&gt; &lt;span class="nt"&gt;here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="CSS"></category></entry><entry><title>PyCharm tips</title><link href="//www.jujens.eu/posts/en/2019/Mar/10/pycharm/" rel="alternate"></link><published>2019-03-10T00:00:00+01:00</published><updated>2019-03-10T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2019-03-10:/posts/en/2019/Mar/10/pycharm/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#view-print-output-immediately" id="id1"&gt;View print output immediately&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#auto-load-env-file" id="id2"&gt;Auto-load .env file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-shell-plus-in-the-integrated-console" id="id3"&gt;Use shell_plus in the integrated console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#make-sure-commit-hooks-run-in-a-venv" id="id4"&gt;Make sure commit hooks run in a venv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="view-print-output-immediately"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;View print output immediately&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Add &lt;tt class="docutils literal"&gt;PYTHONUNBUFFERED=1&lt;/tt&gt; in run config or &lt;tt class="docutils literal"&gt;.env&lt;/tt&gt; (only use &lt;tt class="docutils literal"&gt;.env&lt;/tt&gt; if you use the plugin). This is meant to immediately view the output …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#view-print-output-immediately" id="id1"&gt;View print output immediately&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#auto-load-env-file" id="id2"&gt;Auto-load .env file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-shell-plus-in-the-integrated-console" id="id3"&gt;Use shell_plus in the integrated console&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#make-sure-commit-hooks-run-in-a-venv" id="id4"&gt;Make sure commit hooks run in a venv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="view-print-output-immediately"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;View print output immediately&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Add &lt;tt class="docutils literal"&gt;PYTHONUNBUFFERED=1&lt;/tt&gt; in run config or &lt;tt class="docutils literal"&gt;.env&lt;/tt&gt; (only use &lt;tt class="docutils literal"&gt;.env&lt;/tt&gt; if you use the plugin). This is meant to immediately view the output of the print function without the need for flush=True.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="auto-load-env-file"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Auto-load .env file&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Install the &lt;a class="reference external" href="https://plugins.jetbrains.com/plugin/7861-envfile"&gt;EnvFile&lt;/a&gt; and &lt;a class="reference external" href="https://plugins.jetbrains.com/plugin/9525--env-files-support"&gt;.env file support&lt;/a&gt; plugins. Then configure the Django server to run with the custom command &lt;tt class="docutils literal"&gt;runserver_plus&lt;/tt&gt; (optional) and in the &lt;em&gt;EnvFile&lt;/em&gt; tab, tick &lt;em&gt;Enable EnvFile&lt;/em&gt; and in the box below, add you &lt;tt class="docutils literal"&gt;.env&lt;/tt&gt; file. Do the same for pytest.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Use [direnv](&lt;a class="reference external" href="http://direnv.net/"&gt;http://direnv.net/&lt;/a&gt;) to autoload the &lt;tt class="docutils literal"&gt;.env&lt;/tt&gt;. To do this, create a &lt;tt class="docutils literal"&gt;.envrc&lt;/tt&gt; file with the content below and run &lt;tt class="docutils literal"&gt;direnv allow .&lt;/tt&gt; to allow the &lt;tt class="docutils literal"&gt;.envrc&lt;/tt&gt; file to be loaded:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
# Auto load venv.
layout_pipenv
# Auto load .env file
dotenv
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Add this to the &lt;tt class="docutils literal"&gt;activate&lt;/tt&gt; script:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TERMINAL_EMULATOR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;JetBrains-JediTerm&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; -f .env &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    load-dotenv .env
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="use-shell-plus-in-the-integrated-console"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Use shell_plus in the integrated console&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use this starting script in &lt;em&gt;Build, Execution, Deployment&lt;/em&gt; &amp;gt; &lt;em&gt;Console&lt;/em&gt; &amp;gt; &lt;em&gt;Django console&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c1"&gt;# Load env var&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;environ&lt;/span&gt;
&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.env'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Python &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt; on &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Django &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_version&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;WORKING_DIR_AND_PYTHON_PATHS&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;'setup'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;django&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;django_manage_shell&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;django_manage_shell&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROJECT_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django_extensions.management&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shells&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.core.management.color&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;color_style&lt;/span&gt;

&lt;span class="c1"&gt;# Default settings for shell_plus&lt;/span&gt;
&lt;span class="n"&gt;shell_plus_default_settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'bpython'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'connection_file'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'dont_load'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="s1"&gt;'ipython'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'kernel'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'no_browser'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'no_color'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'notebook'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'plain'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;           &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'print_sql'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ptipython'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'ptpython'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'pythonpath'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'quiet_load'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'settings'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'traceback'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'use_pythonrc'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'verbosity'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'vi_mode'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'dont_load'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;objects_to_import&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shells&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;import_objects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shell_plus_default_settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color_style&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;objects_to_import&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="make-sure-commit-hooks-run-in-a-venv"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Make sure commit hooks run in a venv&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can use this script:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; -eu

&lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="nv"&gt;INSIDE_DOCKER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;grep -q docker /proc/self/cgroup &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;readonly&lt;/span&gt; &lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="c1"&gt;# To be sure $&amp;#64; will only contain the parameters of the command, not the command itself.
&lt;/span&gt;&lt;span class="nb"&gt;shift&lt;/span&gt;

&lt;span class="c1"&gt;# If we are already in a venv or if the are in docker, run directly.
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -v VIRTUAL_ENV &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INSIDE_DOCKER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Already in venv&amp;quot;&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="c1"&gt;# Load bashrc to be sure PATH is correctly set. We can't do this before this it could mess up with the enabled venv.
&lt;/span&gt;    &lt;span class="c1"&gt;# We don't want to fail if the bashrc file contains unbound variables.
&lt;/span&gt;    &lt;span class="nb"&gt;set&lt;/span&gt; +u
    &lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Bash RC file not found&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;set&lt;/span&gt; -u
    &lt;span class="c1"&gt;# If not and pipenv is installed and we have a Pipfile, run with pipenv.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; -v pipenv &amp;gt; /dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -f Pipfile &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Running in venv with pipenv&amp;quot;&lt;/span&gt;
        pipenv run &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

        &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt;
    &lt;span class="c1"&gt;# If poetry is installed and we have a pyproject.toml, run with poetry.
&lt;/span&gt;    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt; -v poetry &amp;gt; /dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -f pyproject.toml &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Running in venv with poetry&amp;quot;&lt;/span&gt;
    poetry run &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Not in an virtual env and don't know how to run in one.&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
        &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Then, if you use &lt;a class="reference external" href="https://pre-commit.com/"&gt;pre-commit&lt;/a&gt;, you can do something like this:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;flake8&lt;/span&gt;
  &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;flake8&lt;/span&gt;
  &lt;span class="nt"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;./bin/ensure-runs-in-venv.sh&lt;/span&gt;
  &lt;span class="nt"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'/snapshots/.*\.py$'&lt;/span&gt;
  &lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;flake8&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;
  &lt;span class="nt"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;system&lt;/span&gt;
  &lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category><category term="IDE"></category><category term="PyCharm"></category></entry><entry><title>ZSH tips</title><link href="//www.jujens.eu/posts/en/2018/Oct/09/zbell/" rel="alternate"></link><published>2018-10-09T00:00:00+02:00</published><updated>2018-10-09T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-10-09:/posts/en/2018/Oct/09/zbell/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#zbell" id="id1"&gt;ZBell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="zbell"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;ZBell&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Useful to have a notification when a long command completes.&lt;/p&gt;
&lt;p&gt;To enable it, add &lt;tt class="docutils literal"&gt;zbell&lt;/tt&gt; to your plugins array if you are using &lt;a class="reference external" href="https://github.com/robbyrussell/oh-my-zsh"&gt;oh-my-zsh&lt;/a&gt; or source the definition file.&lt;/p&gt;
&lt;p&gt;To configure:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The minimum time commands must take for the notification to happen, use: &lt;tt class="docutils literal"&gt;ZBELL_DURATION&lt;/tt&gt;. For instance &lt;tt class="docutils literal"&gt;ZBELL_DURATION …&lt;/tt&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#zbell" id="id1"&gt;ZBell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="zbell"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;ZBell&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Useful to have a notification when a long command completes.&lt;/p&gt;
&lt;p&gt;To enable it, add &lt;tt class="docutils literal"&gt;zbell&lt;/tt&gt; to your plugins array if you are using &lt;a class="reference external" href="https://github.com/robbyrussell/oh-my-zsh"&gt;oh-my-zsh&lt;/a&gt; or source the definition file.&lt;/p&gt;
&lt;p&gt;To configure:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The minimum time commands must take for the notification to happen, use: &lt;tt class="docutils literal"&gt;ZBELL_DURATION&lt;/tt&gt;. For instance &lt;tt class="docutils literal"&gt;ZBELL_DURATION=60&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;The command zbell must ignore, use: &lt;tt class="docutils literal"&gt;ZBELL_CMD_IGNORE&lt;/tt&gt;. For instance: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ZBELL_CMD_IGNORE=($EDITOR&lt;/span&gt; $PAGER git nano less emacs bash ssh su tmux zsh &amp;quot;pipenv shell&amp;quot; &amp;quot;python manage.py shell_plus&amp;quot;)&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is the plugin. It was inspired by &lt;a class="reference external" href="https://gist.github.com/jpouellet/5278239/"&gt;https://gist.github.com/jpouellet/5278239/&lt;/a&gt; (I made changes to ignore commands made of multiple words, to report duration only once and to use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;notify-send&lt;/span&gt;&lt;/tt&gt; to send the notification).&lt;/p&gt;
&lt;pre class="code zsh literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env zsh
&lt;/span&gt;
&lt;span class="c1"&gt;# From https://gist.github.com/jpouellet/5278239
&lt;/span&gt;
&lt;span class="c1"&gt;# This script prints a bell character when a command finishes
# if it has been running for longer than $zbell_duration seconds.
# If there are programs that you know run long that you don't
# want to bell after, then add them to $zbell_ignore.
#
# This script uses only zsh builtins so its fast, there's no needless
# forking, and its only dependency is zsh and its standard modules
#
# Written by Jean-Philippe Ouellet &amp;lt;jpo&amp;#64;vt.edu&amp;gt;
# Made available under the ISC license.
&lt;/span&gt;
&lt;span class="c1"&gt;# only do this if we're in an interactive shell
&lt;/span&gt;&lt;span class="o"&gt;[[&lt;/span&gt; -o interactive &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;


&lt;span class="c1"&gt;# get $EPOCHSECONDS. builtins are faster than date(1)
&lt;/span&gt;zmodload zsh/datetime &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;


&lt;span class="c1"&gt;# make sure we can register hooks
&lt;/span&gt;autoload -Uz add-zsh-hook &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

&lt;span class="c1"&gt;# initialize zbell_duration if not set
&lt;/span&gt;&lt;span class="o"&gt;((&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;+zbell_duration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;zbell_duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZBELL_DURATION&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;15&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# initialize zbell_ignore if not set
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="si"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;ZBELL_CMD_IGNORE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; -gt &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; ! &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;+zbell_ignore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nv"&gt;zbell_ignore&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; ignore_cmd in &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZBELL_CMD_IGNORE&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="nv"&gt;zbell_ignore&lt;/span&gt;&lt;span class="o"&gt;+=(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ignore_cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;((&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;+zbell_ignore&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;zbell_ignore&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="nv"&gt;$EDITOR&lt;/span&gt; &lt;span class="nv"&gt;$PAGER&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# initialize it because otherwise we compare a date and an empty string
# the first time we see the prompt. it's fine to have lastcmd empty on the
# initial run because it evaluates to an empty string, and splitting an
# empty string just results in an empty array.
&lt;/span&gt;&lt;span class="nv"&gt;zbell_timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$EPOCHSECONDS&lt;/span&gt;

&lt;span class="c1"&gt;# right before we begin to execute something, store the time it started at
&lt;/span&gt;zbell_begin&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;zbell_timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$EPOCHSECONDS&lt;/span&gt;
    &lt;span class="nv"&gt;zbell_lastcmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# when it finishes, if it's been running longer than $zbell_duration,
# and we dont have an ignored command in the line, then print a bell.
&lt;/span&gt;zbell_end&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zbell_lastcmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="nv"&gt;time_run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="nv"&gt;$EPOCHSECONDS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$zbell_timestamp&lt;/span&gt; &lt;span class="k"&gt;))&lt;/span&gt;
    &lt;span class="nv"&gt;ran_long&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="nv"&gt;$EPOCHSECONDS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$zbell_timestamp&lt;/span&gt; &amp;gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$zbell_duration&lt;/span&gt; &lt;span class="k"&gt;))&lt;/span&gt;

    &lt;span class="nv"&gt;has_ignored_cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; ignore_cmd in &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zbell_ignore&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zbell_lastcmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; *&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ignore_cmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;* &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            &lt;span class="nv"&gt;has_ignored_cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
            &lt;span class="nb"&gt;break&lt;/span&gt;
        &lt;span class="k"&gt;fi&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; ! &lt;span class="nv"&gt;$has_ignored_cmd&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; ran_long &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        notify-send &lt;span class="s2"&gt;&amp;quot;'&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zbell_lastcmd&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' completed in &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;time_run&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="nv"&gt;zbell_lastcmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# register the functions as hooks
&lt;/span&gt;add-zsh-hook preexec zbell_begin
add-zsh-hook precmd zbell_end
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="ZSH"></category><category term="Shell"></category><category term="Linux"></category></entry><entry><title>Bash tricks</title><link href="//www.jujens.eu/posts/en/2018/Oct/03/bash/" rel="alternate"></link><published>2018-10-03T00:00:00+02:00</published><updated>2018-10-03T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-10-03:/posts/en/2018/Oct/03/bash/</id><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#scripts" id="id1"&gt;Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#signals" id="id2"&gt;Signals&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="scripts"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Scripts&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use this at the top of all your Bash scripts to avoid problems:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# Exit on error.
&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -e
&lt;span class="c1"&gt;# Don't allow undefined variable.
&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -u
&lt;span class="c1"&gt;# Make pipeline fail if any command in it fail.
&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o pipefail
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="signals"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Signals&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;See &lt;a class="reference external" href="//www.jujens.eu/posts/en/2015/Jan/09/utiliser-trap-bash/"&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Bash"></category><category term="Shell"></category><category term="Linux"></category></entry><entry><title>Heroku tips</title><link href="//www.jujens.eu/posts/en/2018/Oct/03/heroku/" rel="alternate"></link><published>2018-10-03T00:00:00+02:00</published><updated>2018-10-03T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-10-03:/posts/en/2018/Oct/03/heroku/</id><summary type="html">&lt;div class="section" id="use-an-editor"&gt;
&lt;h2&gt;Use an editor&lt;/h2&gt;
&lt;p&gt;By default there is no editor on Heroku. To get one, you can use the &lt;a class="reference external" href="https://github.com/Ehryk/heroku-nano"&gt;heroku-nano&lt;/a&gt; plugin like this (or by installing as a plugin):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mkdir bin
&lt;span class="nb"&gt;cd&lt;/span&gt; bin
curl https://github.com/Ehryk/heroku-nano/raw/master/heroku-nano-2.5.1/nano.tar.gz --location --silent &amp;gt; nano.tar …&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="section" id="use-an-editor"&gt;
&lt;h2&gt;Use an editor&lt;/h2&gt;
&lt;p&gt;By default there is no editor on Heroku. To get one, you can use the &lt;a class="reference external" href="https://github.com/Ehryk/heroku-nano"&gt;heroku-nano&lt;/a&gt; plugin like this (or by installing as a plugin):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mkdir bin
&lt;span class="nb"&gt;cd&lt;/span&gt; bin
curl https://github.com/Ehryk/heroku-nano/raw/master/heroku-nano-2.5.1/nano.tar.gz --location --silent &amp;gt; nano.tar.gz
tar -xvf nano.tar.gz
chmod +x nano
&lt;span class="nb"&gt;cd&lt;/span&gt; -
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;realpath bin&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Then use &lt;tt class="docutils literal"&gt;nano README.md&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="papertail"&gt;
&lt;h2&gt;Papertail&lt;/h2&gt;
&lt;div class="section" id="download-logs"&gt;
&lt;h3&gt;Download logs&lt;/h3&gt;
&lt;p&gt;This requires &lt;a class="reference external" href="https://httpie.org/"&gt;httpie&lt;/a&gt;. But you can adapt this to use curl instead.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;​
&lt;span class="nb"&gt;set&lt;/span&gt; -eu

&lt;span class="c1"&gt;# Change this to start at another date.
&lt;/span&gt;&lt;span class="nv"&gt;start_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2019&lt;/span&gt;-08-24
&lt;span class="nv"&gt;nb_days_to_download&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;18&lt;/span&gt;
&lt;span class="c1"&gt;# Set your paper trail token here.
&lt;/span&gt;&lt;span class="nv"&gt;papertrail_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="k"&gt;$(&lt;/span&gt;seq &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;nb_days_to_download&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;log_date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date -I -d &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;start_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; +&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; days&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
  mkdir -p &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
  &lt;span class="nb"&gt;pushd&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; log_hour in &lt;span class="k"&gt;$(&lt;/span&gt;seq -f &lt;span class="s2"&gt;&amp;quot;%02g&amp;quot;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; ! -f &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_hour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tsv.gz&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        http --follow &lt;span class="s2"&gt;&amp;quot;https://papertrailapp.com/api/v1/archives/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_hour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/download&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;X-Papertrail-Token:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;papertrail_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_date&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;log_hour&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tsv.gz&amp;quot;&lt;/span&gt;
      &lt;span class="k"&gt;fi&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;
  &lt;span class="nb"&gt;popd&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="download-files"&gt;
&lt;h2&gt;Download files&lt;/h2&gt;
&lt;div class="section" id="from-google-drive"&gt;
&lt;h3&gt;From google drive&lt;/h3&gt;
&lt;p&gt;Define this function:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
gdrive-download&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;file_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
    &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
    &lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://drive.google.com/uc?export=download&amp;amp;id=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Downloading &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nv"&gt;CONFIRM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;base_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -O- &lt;span class="p"&gt;|&lt;/span&gt; sed -rn &lt;span class="s1"&gt;'s/.*confirm=([0-9A-Za-z_]+).*/\1/p'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
    wget --load-cookies /tmp/cookies.txt &lt;span class="s2"&gt;&amp;quot;https://drive.google.com/uc?export=download&amp;amp;confirm=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFIRM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;id=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -O &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    rm -rf /tmp/cookies.txt
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And use it like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gdrive-download&lt;/span&gt; FILE_ID_FROM_THE_SHARE_LINK DEST_FILENAME&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="devops"></category><category term="Heroku"></category></entry><entry><title>Python tricks</title><link href="//www.jujens.eu/posts/en/2018/Oct/03/python/" rel="alternate"></link><published>2018-10-03T00:00:00+02:00</published><updated>2018-10-03T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-10-03:/posts/en/2018/Oct/03/python/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#inspect-tls-certificates-with-requests" id="id1"&gt;Inspect TLS certificates with requests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="inspect-tls-certificates-with-requests"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Inspect TLS certificates with requests&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use the snippet below to capture and inspect the certificates of a distant site and its chain with &lt;a class="reference external" href="http://docs.python-requests.org/en/master/"&gt;requests&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;HTTPResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urllib3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPResponse&lt;/span&gt;
&lt;span class="n"&gt;orig_HTTPResponse__init__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HTTPResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_HTTPResponse__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;orig_HTTPResponse__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs …&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#inspect-tls-certificates-with-requests" id="id1"&gt;Inspect TLS certificates with requests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="inspect-tls-certificates-with-requests"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Inspect TLS certificates with requests&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use the snippet below to capture and inspect the certificates of a distant site and its chain with &lt;a class="reference external" href="http://docs.python-requests.org/en/master/"&gt;requests&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;HTTPResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urllib3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPResponse&lt;/span&gt;
&lt;span class="n"&gt;orig_HTTPResponse__init__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HTTPResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_HTTPResponse__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;orig_HTTPResponse__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_certificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_certificate&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="n"&gt;HTTPResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_HTTPResponse__init__&lt;/span&gt;

&lt;span class="n"&gt;HTTPAdapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adapters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPAdapter&lt;/span&gt;
&lt;span class="n"&gt;orig_HTTPAdapter_build_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HTTPAdapter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build_response&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_HTTPAdapter_build_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orig_HTTPAdapter_build_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_certificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_certificate&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;span class="n"&gt;HTTPAdapter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_HTTPAdapter_build_response&lt;/span&gt;

&lt;span class="n"&gt;HTTPSConnection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urllib3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPSConnection&lt;/span&gt;
&lt;span class="n"&gt;orig_HTTPSConnection_connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HTTPSConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_HTTPSConnection_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;orig_HTTPSConnection_connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_certificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_peer_certificate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_peer_cert_chain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="n"&gt;HTTPSConnection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_HTTPSConnection_connect&lt;/span&gt;


&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://www.jujens.eu'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_certificate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_subject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;peer_cert_chain&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_subject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Sources: &lt;a class="reference external" href="https://stackoverflow.com/a/52072170"&gt;https://stackoverflow.com/a/52072170&lt;/a&gt; and &lt;a class="reference external" href="https://stackoverflow.com/a/47931103"&gt;https://stackoverflow.com/a/47931103&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category></entry><entry><title>Deploy to your test server with git hooks</title><link href="//www.jujens.eu/posts/en/2018/Sep/09/deploy-test-git-hooks/" rel="alternate"></link><published>2018-09-09T00:00:00+02:00</published><updated>2018-09-09T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-09-09:/posts/en/2018/Sep/09/deploy-test-git-hooks/</id><summary type="html">&lt;p&gt;You probably already wanted to have your own test environment to allow others in the company to tests what you did. Perhaps you have a common one, but as your team is growing, it is probable that the common environment is a bottleneck and you wish each developer could have …&lt;/p&gt;</summary><content type="html">&lt;p&gt;You probably already wanted to have your own test environment to allow others in the company to tests what you did. Perhaps you have a common one, but as your team is growing, it is probable that the common environment is a bottleneck and you wish each developer could have its own to test things in isolation. That's the subject of this article where we will create such an environment and deploy to it with a simple &lt;tt class="docutils literal"&gt;git push&lt;/tt&gt; (a lot like &lt;a class="reference external" href="https://heroku.com"&gt;Heroku&lt;/a&gt; but a lot cheaper). You will also have full control over it and you will be able to modify the files directly on the server if needed (just don't do that last part in production ;-)).&lt;/p&gt;
&lt;p&gt;In a nutshell, we need to support:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Code updates:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Push to a current branch.&lt;/li&gt;
&lt;li&gt;Force push to a current branch&lt;/li&gt;
&lt;li&gt;Erasing unclean work tree on the server&lt;/li&gt;
&lt;li&gt;Pushing a new branch&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Restart of the server (meaning the test environments must be up and running if the server restarts).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Environment variables to configure the application.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To achieve all this, all you need is a linux server. Your machine or a VM will do if you want to test along. If you want to use a VM, you may want to check &lt;a class="reference external" href="//www.jujens.eu/posts/en/2015/Nov/12/libvirt/"&gt;my tips for libvirt to use a static ip for the VM&lt;/a&gt; and &lt;a class="reference external" href="//www.jujens.eu/posts/en/2015/Nov/09/VirtualBox-connect-guest/"&gt;Connect to a VirtualBox VM&lt;/a&gt; to ease SSH connection in you VM.&lt;/p&gt;
&lt;p&gt;To do it for real, a server in the office or in the cloud will do. If you need help, leave a comment, I'll do my best to provide feedback.&lt;/p&gt;
&lt;p&gt;For the purpose of this tutorial, we will deploy a &lt;a class="reference external" href="https://gitlab.com/Jenselme/hello-flask"&gt;small hello work app&lt;/a&gt;. You can fork it and use the fork as a remote repository if you want to follow along. The app is made in Python and there are a few Python specific things here and there but globally, you should be able to adapt it to any other languages. Leave a comment if you need help.&lt;/p&gt;
&lt;p&gt;Before we start, some precision:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;If your server is running SELinux, you'll have to add proper context (the web one) to some file and allow the web server to connect to the UNIX or TCP&amp;nbsp;socket of the application server. I won't go into this here, the tutorial is already long enough.&lt;/li&gt;
&lt;li&gt;I'll use jujens.bl.test as my test domain. Replace it with your own.&lt;/li&gt;
&lt;li&gt;Commands that must be run as root with start with &lt;tt class="docutils literal"&gt;#&lt;/tt&gt; and as a normal user with &lt;tt class="docutils literal"&gt;$&lt;/tt&gt;. I'll precise the host too.&lt;/li&gt;
&lt;li&gt;You need new commits to push the code with git. If you change nothing, no hooks (more on that later) will run on the server because git is smart enough to see nothing changed.&lt;/li&gt;
&lt;li&gt;I assume your OS runs systemd. If not, adapt the commands.&lt;/li&gt;
&lt;li&gt;I'll present things in a tutorial manner so you can understand and follow what I do. Go to the &lt;a class="reference internal" href="#summary"&gt;Summary&lt;/a&gt; section to view a recap and what you need to do each time you want to add a developer.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-the-server" id="id1"&gt;Prepare the server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-the-repo" id="id2"&gt;Prepare the repo&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-git" id="id3"&gt;Configure git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-the-server-repo" id="id4"&gt;Prepare the server repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#how-to-send-the-code-to-the-server" id="id5"&gt;How to send the code to the server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configuring-the-web-server" id="id6"&gt;Configuring the web server&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#basic-setup-of-the-application-server" id="id7"&gt;Basic setup of the application server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#basic-nginx-configuration" id="id8"&gt;Basic nginx configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configuration-for-multiple-users" id="id9"&gt;Configuration for multiple users&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configuring-the-application-server" id="id10"&gt;Configuring the application server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configuring-nginx" id="id11"&gt;Configuring nginx&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#static-files" id="id12"&gt;Static files&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#testing-deployment" id="id13"&gt;Testing deployment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#environment-variables" id="id14"&gt;Environment variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#secure-access" id="id15"&gt;Secure access&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#going-further" id="id16"&gt;Going further&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#summary" id="id17"&gt;Summary&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#full-configurations" id="id18"&gt;Full configurations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="prepare-the-server"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Prepare the server&lt;/a&gt;&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Get a linux server (cloud, VM, your machine, Raspberry Pi, …)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Install the prerequisites&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;SSH&lt;/li&gt;
&lt;li&gt;git&lt;/li&gt;
&lt;li&gt;nginx (apache or any other web server can work too, you'll have to adapt the conf though)&lt;/li&gt;
&lt;li&gt;Python (or anything else you need to run your application)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Configure SSH: you probably want to edit &lt;tt class="docutils literal"&gt;/etc/ssh/sshd_config&lt;/tt&gt; to disallow direct root login (with &lt;tt class="docutils literal"&gt;PermitRootLogin no&lt;/tt&gt;), force SSH key usage (with &lt;tt class="docutils literal"&gt;PasswordAuthentication no&lt;/tt&gt;) and perhaps change the default port (eg with &lt;tt class="docutils literal"&gt;Port 422&lt;/tt&gt;). Search the internet to learn more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Enable SSH: on the server, run &lt;tt class="docutils literal"&gt;systemctl start sshd&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;systemctl enable sshd&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Configure the firewall to let SSH and HTTP traffic through (adapt these commands if you changed any ports):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;With firewalld: &lt;tt class="docutils literal"&gt;# &lt;span class="pre"&gt;firewall-cmd&lt;/span&gt; &lt;span class="pre"&gt;--add-service=http&lt;/span&gt; &lt;span class="pre"&gt;--permanent&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class="pre"&gt;firewall-cmd&lt;/span&gt; &lt;span class="pre"&gt;--add-service=http&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;# &lt;span class="pre"&gt;firewall-cmd&lt;/span&gt; &lt;span class="pre"&gt;--add-service=ssh&lt;/span&gt; &lt;span class="pre"&gt;--permanent&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class="pre"&gt;firewall-cmd&lt;/span&gt; &lt;span class="pre"&gt;--add-service=ssh&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;With iptable: &lt;tt class="docutils literal"&gt;# iptables &lt;span class="pre"&gt;-t&lt;/span&gt; filter &lt;span class="pre"&gt;-A&lt;/span&gt; INPUT &lt;span class="pre"&gt;-p&lt;/span&gt; TCP &lt;span class="pre"&gt;--dport&lt;/span&gt; 22 &lt;span class="pre"&gt;-j&lt;/span&gt; ACCEPT&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;# iptables &lt;span class="pre"&gt;-t&lt;/span&gt; filter &lt;span class="pre"&gt;-A&lt;/span&gt; INPUT &lt;span class="pre"&gt;-p&lt;/span&gt; TCP &lt;span class="pre"&gt;--dport&lt;/span&gt; 80 &lt;span class="pre"&gt;-j&lt;/span&gt; ACCEPT&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create at least one user (each dev should have their own user, more on that later). I'll use &lt;tt class="docutils literal"&gt;jujens&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the &lt;tt class="docutils literal"&gt;deploy&lt;/tt&gt; group: &lt;tt class="docutils literal"&gt;# groupadd &lt;span class="pre"&gt;-r&lt;/span&gt; deploy&lt;/tt&gt; and add your user to it: &lt;tt class="docutils literal"&gt;# usermod &lt;span class="pre"&gt;-aG&lt;/span&gt; deploy jujens&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Start and enable nginx: &lt;tt class="docutils literal"&gt;# systemctl start nginx&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;# systemctl enable nginx&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To use the &lt;tt class="docutils literal"&gt;bl.test&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;jujens.bl.test&lt;/tt&gt; domains, you must either modify your &lt;tt class="docutils literal"&gt;/etc/hosts&lt;/tt&gt; by adding something like this (change the ip of the server):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
192.168.122.45 bl.test jujens.bl.test
&lt;/pre&gt;
&lt;p&gt;Or use dnsmasq to redirect all requests made to &lt;tt class="docutils literal"&gt;bl.test&lt;/tt&gt; and its subdomains to an ip. See &lt;a class="reference external" href="//www.jujens.eu/posts/en/2018/Sep/08/NetworkManager-dnsmasq/"&gt;my article on that&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If your server is publicly accessible, you may add a wildcard entry to your DNS server so all subdomains of test.mypublicdomain.com are served by the test server. This way you will avoid the need to change your DNS configuration when you add a new developer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="prepare-the-repo"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Prepare the repo&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="configure-git"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Configure git&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, we will configure git. You can use a global configuration by editing &lt;tt class="docutils literal"&gt;/etc/gitconfig&lt;/tt&gt; (users can still change it for all their repos in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.gitconfig&lt;/span&gt;&lt;/tt&gt; or per each repo in &lt;tt class="docutils literal"&gt;.git/config&lt;/tt&gt;).&lt;/p&gt;
&lt;p class="tip"&gt;
Note that if you intend to do other things than git deploys with your server, the global configuration may not be the best choice.
&lt;/p&gt;&lt;p&gt;Here is the git configuration we'll use&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[core]&lt;/span&gt;
    &lt;span class="na"&gt;hooksPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/etc/git/hooks&lt;/span&gt;

&lt;span class="k"&gt;[receive]&lt;/span&gt;
    &lt;span class="na"&gt;denyCurrentBranch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;updateInstead&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can check it by running:  &lt;tt class="docutils literal"&gt;git config receive.denyCurrentBranch&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;git config core.hooksPath&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="tip"&gt;
You must adapt the path to where the git hooks will be. If you choose a per repo configuration, you don't need to specify it and it will default to &lt;code&gt;.git/hooks&lt;/code&gt;
&lt;/p&gt;&lt;p class="note"&gt;
By default git won't allow you to push to a non bare repo (ie a repo in which you can access files easily) because it is dangerous. But in our case, it is required, otherwise, we won't be able to push anything while making the site work. That's the point of the ``denyCurrentBranch = updateInstead`` option. See &lt;a href="https://git-scm.com/docs/git-config#git-config-receivedenyCurrentBranch"&gt;the documentation&lt;/a&gt; for more details.
&lt;/p&gt;&lt;p&gt;Now we can create the directory where the global hooks will lie: &lt;tt class="docutils literal"&gt;mkdir &lt;span class="pre"&gt;-p&lt;/span&gt; /etc/git/hooks&lt;/tt&gt;. We will add scripts here later.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="prepare-the-server-repo"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Prepare the server repo&lt;/a&gt;&lt;/h3&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Clone the remote repo on your dev machine (where you want) so you can push from it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Clone the remote repo on the server. You could also push directly from your dev machine to it but I find it easier this way (and you still have to create a repo on the server). Do it:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Create the folder &lt;tt class="docutils literal"&gt;/var/www/bl.test/jujens.bl.test&lt;/tt&gt; (the location may seem odd right now, but it will have its importance later): &lt;tt class="docutils literal"&gt;# mkdir &lt;span class="pre"&gt;-p&lt;/span&gt; /var/www/bl.test/jujens.bl.test&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Set user and group: &lt;tt class="docutils literal"&gt;# chown jujens:nginx /var/www/bl.test/jujens.bl.test&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Set the proper permissions: &lt;tt class="docutils literal"&gt;# chmod u=rwX,g=rXs,o=- /var/www/bl.test/jujens.bl.test&lt;/tt&gt; (this will give all permission the current user, read and &amp;quot;execute&amp;quot; permissions to the group and nothing to others. The &lt;tt class="docutils literal"&gt;s&lt;/tt&gt; is there to set the &amp;quot;sticky bit&amp;quot;. Thanks to it, all file created inside the directory will belong to the group you specify.&lt;/li&gt;
&lt;li&gt;Clone: &lt;tt class="docutils literal"&gt;# git clone &lt;span class="pre"&gt;https://gitlab.com/Jenselme/hello-flask.git&lt;/span&gt; /var/www/bl.test/jujens.bl.test&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Add the test remote on your dev repo (so you can push to the test server): &lt;tt class="docutils literal"&gt;$ git remote add test &lt;span class="pre"&gt;jujens&amp;#64;bl.test:/var/www/bl.test/jujens.bl.test&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Check everything is configure properly with a &lt;tt class="docutils literal"&gt;$ git push test&lt;/tt&gt; It should output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
The authenticity of host 'bl.test (192.168.122.45)' can't be established.
ECDSA key fingerprint is SHA256:nb/a1ypBTTgahruVf92GzLNGTAdrrDi2afIWfXaFAa0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'bl.test' (ECDSA) to the list of known hosts.
Everything up-to-date
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="how-to-send-the-code-to-the-server"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;How to send the code to the server&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, let me explain briefly what git hooks are since we will need them. Simply put, git hooks are scripts that are run before or after certain actions (commit, push, …). They are named &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;pre-ACTION&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;post-ACTION&lt;/span&gt;&lt;/tt&gt; and are handy to automatically run linting before committing or tests before pushing. By default they lie in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PROJECT/.git/hooks&lt;/span&gt;&lt;/tt&gt; (by the way, you can find samples in this folder). Here, we used the &lt;tt class="docutils literal"&gt;hooksPath&lt;/tt&gt; to have global hooks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don't forget to make these script files executable or they won't work&lt;/strong&gt; (I forget almost all the time!).&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://git-scm.com/docs/githooks"&gt;the doc&lt;/a&gt; for more details and the full list of available hooks.&lt;/p&gt;
&lt;p&gt;Now that's you know what git hooks are, we will do each step at a time (git commands are run on you machine):&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Step 1 &lt;em&gt;Push to a current branch&lt;/em&gt;: Nothing to do since we configured git properly. Just modify &lt;tt class="docutils literal"&gt;hello.py&lt;/tt&gt;, commit and &lt;tt class="docutils literal"&gt;git push test&lt;/tt&gt;. You should see the commit and the modified file on the server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Step 2 &lt;em&gt;Force push to a current branch&lt;/em&gt;: Let's say we made a mistake in our previous commit, amended it and want to force push that. Modify the &lt;tt class="docutils literal"&gt;hello.py&lt;/tt&gt; again and do &lt;tt class="docutils literal"&gt;git commit &lt;span class="pre"&gt;--amend&lt;/span&gt; &lt;span class="pre"&gt;-a&lt;/span&gt;&lt;/tt&gt; to amend the last commit. &lt;tt class="docutils literal"&gt;git push test&lt;/tt&gt; will fail but &lt;tt class="docutils literal"&gt;git push test &lt;span class="pre"&gt;--force&lt;/span&gt;&lt;/tt&gt; will do just what we need. This will also work if you have new commits on the test server, just be aware they will be deleted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Step 3 &lt;em&gt;Erasing unclean work tree on the server&lt;/em&gt;: Modify &lt;tt class="docutils literal"&gt;hello.py&lt;/tt&gt; on the server and don't commit. This is meant to simulate a debug modification you made after deploying the app. Now modify &lt;tt class="docutils literal"&gt;hello.py&lt;/tt&gt; on your machine, commit and push. Neither &lt;tt class="docutils literal"&gt;git push test&lt;/tt&gt; nor &lt;tt class="docutils literal"&gt;git push test &lt;span class="pre"&gt;--force&lt;/span&gt;&lt;/tt&gt; will work because the work tree is unclean: you have a modified file whose content would be lost if the push succeeded. You could connect to the machine and run &lt;tt class="docutils literal"&gt;git checkout .&lt;/tt&gt; yourself. But we can automate this with git hooks. Here we want to use the pre-receive hook that will be run before git gets the pushed content. In &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/git/hooks/pre-receive&lt;/span&gt;&lt;/tt&gt; (or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.git/hooks/pre-receive&lt;/span&gt;&lt;/tt&gt; if you want local hooks, I won't precise again), add:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;
&lt;span class="c1"&gt;# We launch the command in a subshell to avoid impacting the true environment with our unset.
# We unset GIT_DIR because it points to the wrong directory.
# We are in the .git directory when this hook is run, so we need to move one step up to run git commands.
# We then force a checkout of the repo to discard any changes.
&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;unset&lt;/span&gt; GIT_DIR &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout -f &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;And voilà! Our &lt;tt class="docutils literal"&gt;git push&lt;/tt&gt; works!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Step 4 &lt;em&gt;Pushing a new branch&lt;/em&gt;: this must be done once git received all the commits with the post-receive hook to update to the new branch. Git hooks are generally passed some parameters so we can do &amp;quot;smart&amp;quot; actions with them. Here, we will read the &lt;tt class="docutils literal"&gt;ref&lt;/tt&gt; (name of the pushed branch). Create &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/git/hooks/post-receive&lt;/span&gt;&lt;/tt&gt; and add:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;
&lt;span class="c1"&gt;# Parameters are passed to stdin, we need to use read to get them. Only ref matters for what we do.
&lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; oldrev newrev ref
&lt;span class="c1"&gt;# By default, ref contains refs/heads/branch-name. We use bash substitution mechanism to remove &amp;quot;refs/heads/&amp;quot;.
&lt;/span&gt;&lt;span class="nv"&gt;branch_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;/refs&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="nv"&gt;heads&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Once again, force a checkout to the branch.
&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;unset&lt;/span&gt; GIT_DIR &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout -f &lt;span class="nv"&gt;$branch_name&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now we can correctly push our code the repo on the test server. On big leap forward. Now let's see how we can configure the server.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="configuring-the-web-server"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Configuring the web server&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="basic-setup-of-the-application-server"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Basic setup of the application server&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, we will prepare our venv (or whatever else you need in your language) with the proper dependencies. This section must be adapted if you are not using Python. Run on the server:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the venv: &lt;tt class="docutils literal"&gt;$ python3 &lt;span class="pre"&gt;-m&lt;/span&gt; venv .venv&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Activate it: &lt;tt class="docutils literal"&gt;$ source .venv/bin/activate&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Install the dependencies: &lt;tt class="docutils literal"&gt;$ pip install &lt;span class="pre"&gt;-r&lt;/span&gt; requirements.txt&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Start the application server: &lt;tt class="docutils literal"&gt;$ gunicorn hello:app&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Check it is running with &lt;tt class="docutils literal"&gt;$ curl localhost:8000&lt;/tt&gt; You should see the following output&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Hello World!
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p class="tip"&gt;
In a true server, you may want to use &lt;code&gt;--forwarded-allow-ips&lt;/code&gt; to limit who can connect to guincorn. See: &lt;a href="http://docs.gunicorn.org/en/latest/deploy.html"&gt;gunicorn's documentation&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;Now that it's done, we can add to the post-receive hook (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/git/hooks/post-receive&lt;/span&gt;&lt;/tt&gt;) the following line to update our venv each time code is pushed:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# We are again in .git by default.
&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip install -r requirements.txt &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="basic-nginx-configuration"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id8"&gt;Basic nginx configuration&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Create nginx configuration file in &lt;tt class="docutils literal"&gt;/etc/nginx/conf.d/bl.test.conf&lt;/tt&gt; (or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/nginx/site-enabled/bl.test.conf&lt;/span&gt;&lt;/tt&gt; depending on your system, I'll use &lt;tt class="docutils literal"&gt;/etc/nginx/conf.d&lt;/tt&gt; for the rest of this tutorial) with this content:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;jujens.bl.test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# Put it to the folder that will contains all the repos.
&lt;/span&gt;    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/bl.test/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Prevent access to source files.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.*\.pyc?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Prevent access to git
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.git&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Relay everything else to the application server.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Test the configuration with &lt;tt class="docutils literal"&gt;nginx &lt;span class="pre"&gt;-t&lt;/span&gt;&lt;/tt&gt; and if everything is fine, reload nginx: &lt;tt class="docutils literal"&gt;systemctl reload nginx&lt;/tt&gt;. On your development machine, run &lt;tt class="docutils literal"&gt;curl jujens.bl.test&lt;/tt&gt; to check everything is fine. You should see something like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Hello World!
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="configuration-for-multiple-users"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id9"&gt;Configuration for multiple users&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the basic configuration section, we used a TCP socket (with a port) to access our application server. It works but if you want to add an environment for a new developer, you will need to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Find an used port and configure gunicorn to use it.&lt;/li&gt;
&lt;li&gt;Add a new nginx configuration so nginx accept request from the proper domain and routes them to the proper application server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Thankfully, we can also use another kind of sockets: UNIX sockets. They exist as files on the server and if named with a proper convention, we can route our traffic easily. That's why I suggested to used the domain as the name of the folder that contains the code. It should become obvious once we completed it.&lt;/p&gt;
&lt;div class="section" id="configuring-the-application-server"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id10"&gt;Configuring the application server&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We will rely on systemd to start and restart the application servers. First, create a file named &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/systemd/system/gunicorn&amp;#64;.service&lt;/span&gt;&lt;/tt&gt;. It is a service template: it is meant to run multiple instances of a service based on a name (&lt;tt class="docutils literal"&gt;jujens.bl.test&lt;/tt&gt; for instance). The name will be accessible as a variable (&lt;tt class="docutils literal"&gt;%i&lt;/tt&gt;) in the template so we can alter the behavior of the service based on it.&lt;/p&gt;
&lt;p&gt;Put this content in the file (adapted from &lt;a class="reference external" href="http://docs.gunicorn.org/en/stable/deploy.html#systemd"&gt;http://docs.gunicorn.org/en/stable/deploy.html#systemd&lt;/a&gt;):&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;gunicorn daemon for %i&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/run/gunicorn/%i.pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PATH=/var/www/bl.test/%i/.venv/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin&amp;quot;&lt;/span&gt;
&lt;span class="na"&gt;RuntimeDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;gunicorn&lt;/span&gt;
&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/bl.test/%i&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/bl.test/%i/.venv/bin/gunicorn \
        --pid /var/run/gunicorn/%i.pid   \
        --bind unix:/var/run/gunicorn/%i.sock \
        hello:app&lt;/span&gt;
&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s TERM $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-failure&lt;/span&gt;
&lt;span class="na"&gt;RestartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5s&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I won't go into the details here (&lt;a class="reference external" href="https://wiki.archlinux.org/index.php/Systemd#Writing_unit_files"&gt;archlinux has a great doc for that&lt;/a&gt;). It is just how we create new unit in systemd. A unit being used to run a service. We use a description and dependencies in the &lt;tt class="docutils literal"&gt;Unit&lt;/tt&gt; section. We then define the service:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;PIDFile&lt;/tt&gt; is used by systemd to know whether the service is working.&lt;/li&gt;
&lt;li&gt;We define as who the service will run.&lt;/li&gt;
&lt;li&gt;We update the path so it can find our venv.&lt;/li&gt;
&lt;li&gt;We defined the working directory to where the app of any given user will live thanks to &lt;tt class="docutils literal"&gt;%i&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;We defined how we want to start the service and how it can be reloaded and restarted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="note"&gt;
I didn't use the &lt;code&gt;--reload&lt;/code&gt; option of guincorn. That is because we may need to update the dependencies of our project before restarting it.
&lt;/p&gt;&lt;p class="tip"&gt;
You may want to use the &lt;code&gt;--worker X&lt;/code&gt; option to run multiple worker and thus allow your app to handle more traffic. In a test server it may not be needed though.
&lt;/p&gt;&lt;p&gt;Now we need to &amp;quot;tell systemd&amp;quot; the file has changed with &lt;tt class="docutils literal"&gt;systemctl &lt;span class="pre"&gt;daemon-reload&lt;/span&gt;&lt;/tt&gt;. We must also prepare the directories required by gunicorn to run:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Where the PID and socket files will be: &lt;tt class="docutils literal"&gt;mkdir &lt;span class="pre"&gt;-p&lt;/span&gt; /var/run/gunicorn&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Correct permissions: &lt;tt class="docutils literal"&gt;chmod u=rwX,g=rX,o=- /var/run/gunicorn/&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can now start and enable the server by using the template and specifying the name of the instance like this: &lt;tt class="docutils literal"&gt;guincorn&amp;#64;DOMAIN&lt;/tt&gt;. Or in my case: &lt;tt class="docutils literal"&gt;systemctl start gunicorn&amp;#64;jujens.bl.test&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;systemctl enable gunicorn&amp;#64;jujens.bl.test&lt;/tt&gt;&lt;/p&gt;
&lt;p class="tip"&gt;
The trailing &lt;code&gt;.service&lt;/code&gt; in the service name is optional.
&lt;/p&gt;&lt;p class="tip"&gt;
Use &lt;code&gt;journalctl -u gunicorn@INTANCE&lt;/code&gt; to view the logs. For instance: &lt;code&gt;journalctl -u gunicorn@jujens.bl.test&lt;/code&gt;
&lt;/p&gt;&lt;p class="tip"&gt;
You don't actually need to create the &lt;code&gt;/var/run/gunicorn&lt;/code&gt; directory. &lt;code&gt;systemd&lt;/code&gt; will create it based on the value of &lt;code&gt;RuntimeDirectory&lt;/code&gt; and set the permissions based on the values of &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Group&lt;/code&gt;.
&lt;/p&gt;&lt;p class="tip"&gt;
On Ubuntu, &lt;code&gt;/var/run/&lt;/code&gt; is mounted on a tmpfs so the directory will disappear. It also seems that when you will launch multiple instances, the folder will be deleted and recreated making its usage as described in this tutorial impossible (&lt;code&gt;guincorn&lt;/code&gt; cannot start by putting its PID and Socket directly in &lt;code&gt;/var/run&lt;/code&gt; because of a permission issue). I suggest you use a runtime directory per user with &lt;code&gt;RuntimeDirectory=gunicorn-%i&lt;/code&gt; or create a &lt;code&gt;/var/myrun/&lt;/code&gt; folder and adapt the configuration or dig into how Ubuntu does things.
&lt;/p&gt;&lt;/div&gt;
&lt;div class="section" id="configuring-nginx"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id11"&gt;Configuring nginx&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We need to update the &lt;tt class="docutils literal"&gt;location /&lt;/tt&gt; section of our nginx configuration to use the proper UNIX socket:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://unix:/var/run/gunicorn/&lt;/span&gt;&lt;span class="nv"&gt;$host.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We also need to update the server name into &lt;tt class="docutils literal"&gt;server_name *.bl.test;&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="note"&gt;
nginx will respond with a &lt;em&gt;502 Bad Gateway&lt;/em&gt; if there is no socket for that domain (either because it doesn't exist or because gunicorn is down).
&lt;/p&gt;&lt;div class="section" id="static-files"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id12"&gt;Static files&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;We could use something like &lt;a class="reference external" href="https://github.com/evansd/whitenoise"&gt;whitenoise&lt;/a&gt; to serve our static files. But since we have a nginx server, we can also rely on it to do the job:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;*.bl.test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/bl.test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Prevent access to source files.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.*\.pyc?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Prevent access to git.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.git&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# If you request /page, we will check if /$host/page exists. If so we serve it.
&lt;/span&gt;    &lt;span class="c1"&gt;# Otherwise we pass the request to gunicorn for processing.
&lt;/span&gt;    &lt;span class="c1"&gt;# For instance, if I request jujens.bl.test/requirements.txt, nginx will check whether
&lt;/span&gt;    &lt;span class="c1"&gt;# /var/www/bl.test/jujens.bl.test/requirements.txt exists and serve it to me.
&lt;/span&gt;    &lt;span class="c1"&gt;# /var/www/bl.test comes from the server root and jujens.bl.test from the $host variable.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$host/$uri&lt;/span&gt; &lt;span class="s"&gt;&amp;#64;gunicorn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Relay everything else to the django web server.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;&amp;#64;gunicorn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://unix:/var/run/gunicorn/&lt;/span&gt;&lt;span class="nv"&gt;$host.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p class="warning"&gt;
Serving directly static files this way is insecure. You may want to choose an empty folder as root and relay everything to your app to serve only relevant files. Another good idea would be to put all static assets in a static directory and serve only its content. For Django users, you can adapt the configuration I mention &lt;a href="/posts/en/2018/May/21/django/#use-a-nginx-reverse-proxy-in-dev"&gt;here&lt;/a&gt;.
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="testing-deployment"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id13"&gt;Testing deployment&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;We are almost ready to test the deployment of our app. We still need two things. First, we must configure sudo to allow the user to restart gunicorn (because git hooks are run as the currently logged in user, jujens in my case, they may not be allowed to run &lt;tt class="docutils literal"&gt;systemctl restart&lt;/tt&gt; by default). To do that:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Run &lt;tt class="docutils literal"&gt;visudo&lt;/tt&gt; to edit the sudoers file (&lt;tt class="docutils literal"&gt;visudo&lt;/tt&gt; will check the syntax of the file before exiting. You can use another editor by setting the &lt;tt class="docutils literal"&gt;EDITOR&lt;/tt&gt; environment variable).&lt;/li&gt;
&lt;li&gt;Add at the bottom of the file: &lt;tt class="docutils literal"&gt;%deploy &lt;span class="pre"&gt;ALL=(ALL)&lt;/span&gt; NOPASSWD: /usr/bin/systemctl restart gunicorn&amp;#64;*&lt;/tt&gt; This will allow all users in the &lt;tt class="docutils literal"&gt;deploy&lt;/tt&gt; group to restart any instance of gunicorn. I think it is the easiest way to achieve our goal. Be more restrictive if you need to.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can now add to our post-receive hook (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/git/hooks/post-receive&lt;/span&gt;&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# We move to the folder that contains our code.
# We extract the domain (and guincorn instance name) from the folder
# by keeping only the name of the current directory of the full path.
# Finally, we restart the proper instance of gunicorn.
&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="p"&gt;##*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; sudo systemctl restart &lt;span class="s2"&gt;&amp;quot;gunicorn&amp;#64;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now if you deploy a new commit, gunicorn will restart and if you do &lt;tt class="docutils literal"&gt;curl &lt;span class="pre"&gt;http://jujens.bl.test&lt;/span&gt;&lt;/tt&gt; you will be able to see you modification.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="environment-variables"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id14"&gt;Environment variables&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far so good. But you may want to configure your application on a per user basis (to use a specific database for instance). To do this, you can rely on environment variables as recommended by &lt;a class="reference external" href="https://12factor.net/config"&gt;the twelve factor app&lt;/a&gt;. To do this, we will configure systemd to load an environment file which will contain all our variables. gunicorn will them be able to access them and so will our app.&lt;/p&gt;
&lt;p&gt;To do that:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Add to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;gunicorn&amp;#64;.service&lt;/span&gt;&lt;/tt&gt; file (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/systemd/system/gunicorn&amp;#64;.service&lt;/span&gt;&lt;/tt&gt;), after &lt;tt class="docutils literal"&gt;Environment&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/bl.test/%i/.env&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Notify systemd about the change with: &lt;tt class="docutils literal"&gt;systemctl &lt;span class="pre"&gt;daemon-reload&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You may also want to prevent access to this file with nginx:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/.env$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now create /var/www/bl.test/jujens.test.bl/.env and put in it:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;MY_ENV_VAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Loaded from env&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Redeploy your app, run &lt;tt class="docutils literal"&gt;curl &lt;span class="pre"&gt;http://jujens.bl.test&lt;/span&gt;&lt;/tt&gt; and you should see &lt;tt class="docutils literal"&gt;Loaded from env&lt;/tt&gt; in the response.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="secure-access"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id15"&gt;Secure access&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since this is a test server, you may want to restrict access to the application. You can do this by putting the server in a local network not accessible to the outside world, basic auth or X509 auth. I'll only detail the basic auth method. For X509, see: &lt;a class="reference external" href="https://arcweb.co/securing-websites-nginx-and-client-side-certificate-authentication-linux/"&gt;https://arcweb.co/securing-websites-nginx-and-client-side-certificate-authentication-linux/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To protect your server with a username and a password at the nginx level:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Install &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;httpd-tools&lt;/span&gt;&lt;/tt&gt; (or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;apache2-utils&lt;/span&gt;&lt;/tt&gt; or whatever provides &lt;tt class="docutils literal"&gt;/usr/bin/htpasswd&lt;/tt&gt;)&lt;/li&gt;
&lt;li&gt;Create the password file and add username to it: &lt;tt class="docutils literal"&gt;htpasswd &lt;span class="pre"&gt;-c&lt;/span&gt; /etc/nginx/bl.test.passwd username&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Type password&lt;/li&gt;
&lt;li&gt;Configure nginx to use this file and prevent access without authentication by adding in the &lt;tt class="docutils literal"&gt;server&lt;/tt&gt; block:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;auth_basic&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Test&lt;/span&gt; &lt;span class="s"&gt;server&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;auth_basic_user_file&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/bl.test.passwd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Test the configuration with &lt;tt class="docutils literal"&gt;nginx &lt;span class="pre"&gt;-t&lt;/span&gt;&lt;/tt&gt; and reload if the configuration is good with: &lt;tt class="docutils literal"&gt;systemctl reload nginx&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="going-further"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id16"&gt;Going further&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, we are done and everything should work as intended. I just want to point out some other ways to do things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;You could use the post-receive hooks to move static files into a dedicated folder (eg &lt;tt class="docutils literal"&gt;/var/www/bl.test/static/jujens.bl.test&lt;/tt&gt;) and use &lt;tt class="docutils literal"&gt;/var/www/bl.test/static&lt;/tt&gt; as the root of nginx to be sure not to serve source files. Since it will communicate with gunicorn with a socket, its root need not be where the source lives. You don't need to bother about a dedicated path for each user if your static files contains their hash in their name. You'll have to setup a cleanup mechanism though. I didn't do it in this tutorial to keep things more simple.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;If you repo is big, you can use something like: &lt;tt class="docutils literal"&gt;git &lt;span class="pre"&gt;--work-tree=/var/www/bl.test/jujens.bl.test&lt;/span&gt; &lt;span class="pre"&gt;--git-dir=/home/jujens/bl.test/.git&lt;/span&gt; checkout &lt;span class="pre"&gt;-f&lt;/span&gt;&lt;/tt&gt; to make everyone push to one git repository and update their source tree. You can use the &lt;tt class="docutils literal"&gt;$USER&lt;/tt&gt; environment variable to know who pushed and copy to the proper directory. You'll have to adapt the file structure.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="https://www.digitalocean.com/community/tutorials/how-to-use-git-hooks-to-automate-development-and-deployment-tasks"&gt;A very good article form digital ocean&lt;/a&gt; has almost the same subject as this tutorial (they give more precision about git hooks and handle only static applications).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;You can also extract the subdomain name (jujens in my case) to use just it in your paths and instance names. Something like this should work (see &lt;a class="reference external" href="https://stackoverflow.com/a/33681072/3900519"&gt;https://stackoverflow.com/a/33681072/3900519&lt;/a&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;map&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt; &lt;span class="nv"&gt;$env_name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;default&lt;/span&gt; &lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;~*&lt;/span&gt; &lt;span class="s"&gt;^(?&amp;lt;x_env_name&amp;gt;[a-z0-9]+)\..*&lt;/span&gt; &lt;span class="nv"&gt;$x_env_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;You can also add HTTPS with something like &lt;a class="reference external" href="https://letsencrypt.org/"&gt;let's encrypt&lt;/a&gt; or you usual provider.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Depending on the level of customization you want, you could also use a project like &lt;a class="reference external" href="http://dokku.viewdocs.io/dokku/"&gt;dokku&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="summary"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id17"&gt;Summary&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Thank you for going this far. The article is quite dense and I think it deserves a quick summary. You can also find all the configurations below with a download link.&lt;/p&gt;
&lt;p&gt;So in a nutshell, to setup the server, you need to (refer to &lt;a class="reference internal" href="#prepare-the-server"&gt;Prepare the server&lt;/a&gt; for the details):&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Install the prerequisites.&lt;/li&gt;
&lt;li&gt;Configure SSH.&lt;/li&gt;
&lt;li&gt;Add and configure the base user and group.&lt;/li&gt;
&lt;li&gt;Setup the global domain if possible.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each time you want to add a user, you need to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Add a new DNS entry if you can't use &amp;quot;glob domains&amp;quot;.&lt;/li&gt;
&lt;li&gt;Add a new user in the &lt;tt class="docutils literal"&gt;deploy&lt;/tt&gt; group.&lt;/li&gt;
&lt;li&gt;Prepare the code repository (clone and setup hooks if you didn't choose to use global ones).&lt;/li&gt;
&lt;li&gt;Prepare the environment (&lt;tt class="docutils literal"&gt;.env&lt;/tt&gt; file, venv, …)&lt;/li&gt;
&lt;li&gt;Start the application server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You could use an adaptation of &lt;a class="reference external" href="//www.jujens.eu/static/deploy-test-git-hooks/add-user.sh"&gt;this script&lt;/a&gt; to make your life easier (run as root):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="ch"&gt;&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="c1"&gt;# Usage: ./add-user.sh USERNAME REPO_TO_CLONE
&lt;/span&gt;&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="c1"&gt;# USERNAME: username used for ssh and in the domain
&lt;/span&gt;&lt;span class="ln"&gt; 5 &lt;/span&gt;&lt;span class="c1"&gt;# REPO_TO_CLONE: the repository to clone.
&lt;/span&gt;&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="c1"&gt;# example: ./add-user.sh jujens https://gitlab.com/Jenselme/hello-flask.git
&lt;/span&gt;&lt;span class="ln"&gt; 7 &lt;/span&gt;&lt;span class="c1"&gt;# will create a jujens user to use the jujens.bl.test subdomain with the specified app.
&lt;/span&gt;&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;&lt;span class="c1"&gt;# Configure bash to exit on errors, consider undefined variables as errors
&lt;/span&gt;&lt;span class="ln"&gt;10 &lt;/span&gt;&lt;span class="c1"&gt;# and fail if any step in a pipe does.
&lt;/span&gt;&lt;span class="ln"&gt;11 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -e
&lt;span class="ln"&gt;12 &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -u
&lt;span class="ln"&gt;13 &lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -o pipefail
&lt;span class="ln"&gt;14 &lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;&lt;span class="nv"&gt;GIT_REPO_BASE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/var/www/bl.test&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;&lt;span class="nv"&gt;BASE_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;bl.test&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="nv"&gt;REPO_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GIT_REPO_BASE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_DOMAIN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;&lt;span class="nv"&gt;SUB_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_DOMAIN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Creating user and add to group.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;useradd &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;usermod -aG deploy &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Preparing repo.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;mkdir -p &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;chown jujens:nginx &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;chmod &lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rwX,g&lt;span class="o"&gt;=&lt;/span&gt;rXs,o&lt;span class="o"&gt;=&lt;/span&gt;- &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;git clone &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;&lt;span class="c1"&gt;# Adapt to your needs and language.
&lt;/span&gt;&lt;span class="ln"&gt;34 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Preparing venv&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;&lt;span class="nb"&gt;pushd&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Opening .env file&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; .env
&lt;span class="ln"&gt;38 &lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;    python3 -m venv .venv
&lt;span class="ln"&gt;40 &lt;/span&gt;    &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;.venv/bin/activate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;    pip install -r requirements.txt
&lt;span class="ln"&gt;42 &lt;/span&gt;&lt;span class="nb"&gt;pushd&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Launching service&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;systemctl start &lt;span class="s2"&gt;&amp;quot;gunicorn&amp;#64;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SUB_DOMAIN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;45 &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;gunicorn&amp;#64;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SUB_DOMAIN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;46 &lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;&lt;span class="c1"&gt;# That's assuming you use the default SSH port, if not, adapt.
&lt;/span&gt;&lt;span class="ln"&gt;49 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;To add the git remote: git remote add test &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#64;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASE_DOMAIN&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;50 &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Done&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="section" id="full-configurations"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id18"&gt;Full configurations&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="//www.jujens.eu/static/deploy-test-git-hooks/bl.test.conf"&gt;nginx configuration&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;*.bl.test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/bl.test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;    &lt;span class="kn"&gt;auth_basic&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Test&lt;/span&gt; &lt;span class="s"&gt;server&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;    &lt;span class="kn"&gt;auth_basic_user_file&lt;/span&gt; &lt;span class="s"&gt;/etc/nginx/bl.test.passwd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="c1"&gt;# Prevent access to pyc and py files.
&lt;/span&gt;&lt;span class="ln"&gt;10 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.*\.pyc?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.git&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;       &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/.env$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$host/$uri&lt;/span&gt; &lt;span class="s"&gt;&amp;#64;gunicorn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;    &lt;span class="c1"&gt;# Relay everything else to the django web server.
&lt;/span&gt;&lt;span class="ln"&gt;27 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;&amp;#64;gunicorn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;        &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://unix:/var/run/gunicorn/&lt;/span&gt;&lt;span class="nv"&gt;$host.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;div class="first"&gt;&lt;a href="/static/deploy-test-git-hooks/gunicorn@.service"&gt;gunicorn configuration&lt;/a&gt;&lt;/div&gt;&lt;pre class="code ini literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;gunicorn daemon&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/run/gunicorn/%i.pid&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="na"&gt;Group&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/bl.test/%i/.env&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PATH=/var/www/bl.test/%i/.venv/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;&lt;span class="na"&gt;RuntimeDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;gunicorn&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;&lt;span class="na"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/bl.test/%i&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/bl.test/%i/.venv/bin/gunicorn \
&lt;/span&gt;&lt;span class="ln"&gt;14 &lt;/span&gt;&lt;span class="s"&gt;          --pid /var/run/gunicorn/%i.pid   \
&lt;/span&gt;&lt;span class="ln"&gt;15 &lt;/span&gt;&lt;span class="s"&gt;          --bind unix:/var/run/gunicorn/%i.sock \
&lt;/span&gt;&lt;span class="ln"&gt;16 &lt;/span&gt;&lt;span class="s"&gt;          hello:app&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s TERM $MAINPID&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="na"&gt;PrivateTmp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-failure&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;&lt;span class="na"&gt;RestartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5s&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;git hooks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="//www.jujens.eu/static/deploy-test-git-hooks/pre-receive"&gt;pre-receive&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ln"&gt;1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span class="ln"&gt;2 &lt;/span&gt;&lt;span class="ch"&gt;&lt;/span&gt;
&lt;span class="ln"&gt;3 &lt;/span&gt;&lt;span class="c1"&gt;# We launch the command in a subshell to avoid impacting the true environment with our unset.
&lt;/span&gt;&lt;span class="ln"&gt;4 &lt;/span&gt;&lt;span class="c1"&gt;# We unset GIT_DIR because it points to the wrong directory.
&lt;/span&gt;&lt;span class="ln"&gt;5 &lt;/span&gt;&lt;span class="c1"&gt;# We are in the .git directory when this hook is run, so we need to move one step up to run git commands.
&lt;/span&gt;&lt;span class="ln"&gt;6 &lt;/span&gt;&lt;span class="c1"&gt;# We then force a checkout of the repo to discard any changes.
&lt;/span&gt;&lt;span class="ln"&gt;7 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;unset&lt;/span&gt; GIT_DIR &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout -f &lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;a class="reference external" href="//www.jujens.eu/static/deploy-test-git-hooks/post-receive"&gt;post-receive&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="ch"&gt;&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="c1"&gt;# Parameters are passed to stdin, we need to use read to get them. Only ref matters for what we do.
&lt;/span&gt;&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; oldrev newrev ref
&lt;span class="ln"&gt; 5 &lt;/span&gt;&lt;span class="c1"&gt;# By default, ref contains refs/heads/branch-name. We use bash substitution mechanism to remove &amp;quot;refs/heads/&amp;quot;.
&lt;/span&gt;&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nv"&gt;branch_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;/refs&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="nv"&gt;heads&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="c1"&gt;# Once again, force a checkout to the branch.
&lt;/span&gt;&lt;span class="ln"&gt; 9 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;unset&lt;/span&gt; GIT_DIR &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout -f &lt;span class="nv"&gt;$branch_name&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;&lt;span class="c1"&gt;# You can add additionnal steps to complete checkout on the current branch (install deps, build JS/CSS files, …)
&lt;/span&gt;&lt;span class="ln"&gt;12 &lt;/span&gt;&lt;span class="c1"&gt;# For instance:
&lt;/span&gt;&lt;span class="ln"&gt;13 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip install -r requirements.txt &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;&lt;span class="c1"&gt;# We move to the folder that contains our code.
&lt;/span&gt;&lt;span class="ln"&gt;16 &lt;/span&gt;&lt;span class="c1"&gt;# We extract the domain (and guincorn instance name) from the folder
&lt;/span&gt;&lt;span class="ln"&gt;17 &lt;/span&gt;&lt;span class="c1"&gt;# by keeping only the name of the current directory of the full path.
&lt;/span&gt;&lt;span class="ln"&gt;18 &lt;/span&gt;&lt;span class="c1"&gt;# Finally, we restart the proper instance of gunicorn.
&lt;/span&gt;&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="p"&gt;##*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; sudo systemctl restart &lt;span class="s2"&gt;&amp;quot;gunicorn&amp;#64;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;unit_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;&lt;span class="c1"&gt;# You could simply this line by using the $USER variable and creating BASE_DOMAIN=&amp;quot;bl.test&amp;quot; into ``sudo systemcl restart &amp;quot;gunicorn&amp;#64;${USER}.${BASE_DOMAIN}&amp;quot;``&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="git"></category><category term="devops"></category></entry><entry><title>Use dnsmasq with NetworkManager</title><link href="//www.jujens.eu/posts/en/2018/Sep/08/NetworkManager-dnsmasq/" rel="alternate"></link><published>2018-09-08T00:00:00+02:00</published><updated>2018-09-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-09-08:/posts/en/2018/Sep/08/NetworkManager-dnsmasq/</id><summary type="html">&lt;p&gt;This will, for instance, allow you to redirect all matching domains to a certain server: dnsmasq will intercept the DNS query and return the ip you specified.&lt;/p&gt;
&lt;p&gt;To do this, edit NetworkManager configuration in &lt;tt class="docutils literal"&gt;/etc/NetworkManager/NetworkManager.conf&lt;/tt&gt; and add in the &lt;tt class="docutils literal"&gt;main&lt;/tt&gt; section &lt;tt class="docutils literal"&gt;dns=dnsmasq&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[main]&lt;/span&gt;
&lt;span class="na"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dnsmasq&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This will, for instance, allow you to redirect all matching domains to a certain server: dnsmasq will intercept the DNS query and return the ip you specified.&lt;/p&gt;
&lt;p&gt;To do this, edit NetworkManager configuration in &lt;tt class="docutils literal"&gt;/etc/NetworkManager/NetworkManager.conf&lt;/tt&gt; and add in the &lt;tt class="docutils literal"&gt;main&lt;/tt&gt; section &lt;tt class="docutils literal"&gt;dns=dnsmasq&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[main]&lt;/span&gt;
&lt;span class="na"&gt;dns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;dnsmasq&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can then create a file in &lt;tt class="docutils literal"&gt;/etc/NetworkManager/dnsmasq.d/redirect.conf&lt;/tt&gt; to redirect the domain you want. For instance to redirect &lt;tt class="docutils literal"&gt;jujens.test&lt;/tt&gt; to localhost host, add this line:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/jujens.test/127.0.0.1&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="linux"></category></entry><entry><title>VSCode tips</title><link href="//www.jujens.eu/posts/en/2018/Sep/02/vscode/" rel="alternate"></link><published>2018-09-02T00:00:00+02:00</published><updated>2018-09-02T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-09-02:/posts/en/2018/Sep/02/vscode/</id><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#python" id="id1"&gt;Python&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#venv" id="id2"&gt;venv&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="python"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Python&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="venv"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id2"&gt;venv&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To use a venv with VSCode, add in the folder settings:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;python.pythonPath&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;~/.virtualenvs/bureauxlocaux--Uxk5jFn/bin/python&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;python.unitTest.pyTestEnabled&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="VSCode"></category></entry><entry><title>Deploy your source maps to Rollbar with Ansible</title><link href="//www.jujens.eu/posts/en/2018/Jul/16/deploy-source-maps-rollbar-ansible/" rel="alternate"></link><published>2018-07-16T00:00:00+02:00</published><updated>2018-07-16T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-07-16:/posts/en/2018/Jul/16/deploy-source-maps-rollbar-ansible/</id><summary type="html">&lt;p&gt;I recently had to integrate &lt;a class="reference external" href="https://rollbar.com/"&gt;Rollbar&lt;/a&gt; (a service to track errors) with a JS application. One nice thing about Rollbar is that if you provide it with source maps, it will point to you where the error is in the original unminified code.&lt;/p&gt;
&lt;p&gt;Since the application is deployed with Ansible …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I recently had to integrate &lt;a class="reference external" href="https://rollbar.com/"&gt;Rollbar&lt;/a&gt; (a service to track errors) with a JS application. One nice thing about Rollbar is that if you provide it with source maps, it will point to you where the error is in the original unminified code.&lt;/p&gt;
&lt;p&gt;Since the application is deployed with Ansible, I wanted to upload the source maps with Ansible. There is a built in module to register deploys with Ansible: &lt;a class="reference external" href="https://docs.ansible.com/ansible/latest/modules/rollbar_deployment_module.html"&gt;rollbar_deployment&lt;/a&gt; but that only solves half the problem since it only registers deployments. Example of usage:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;Register deploy&lt;/span&gt;
  &lt;span class="nt"&gt;rollbar_deployment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nt"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;lookup('env','ROLLBAR_API_KEY')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
    &lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
    &lt;span class="nt"&gt;revision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;with:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;{{ env }}&lt;/tt&gt; the environment you are deploying to.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;{{ version }}&lt;/tt&gt; the revision you want to register.&lt;/li&gt;
&lt;li&gt;You also need the &lt;tt class="docutils literal"&gt;ROLLBAR_API_KEY&lt;/tt&gt; to be set and to contain your Rollbar server API key so you can authenticate to Rollbar.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since I didn't found a module already done, I decide to build my own.&lt;/p&gt;
&lt;p&gt;Below is the code of the Ansible module. Place it under &lt;tt class="docutils literal"&gt;library/rollbar_source_maps.py&lt;/tt&gt; in your Ansible project. Note: it only works with Python 3+ and requires the &lt;a class="reference external" href="https://pypi.org/project/requests/"&gt;requests&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;You will then be able to use it with:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;fronts&lt;/span&gt;
  &lt;span class="nt"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;Upload source maps to Rollbar&lt;/span&gt;
      &lt;span class="nt"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;local&lt;/span&gt;
      &lt;span class="nt"&gt;rollbar_source_maps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;src&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}/dist/scripts&amp;quot;&lt;/span&gt;
        &lt;span class="nt"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;base_url&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
        &lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;version&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
        &lt;span class="nt"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;lookup('env','ROLLBAR_API_KEY')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Where:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;{{ src }}&lt;/tt&gt; points to the root of your JS project. The &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; key in the YAML must point to the folder that contains your source maps. Feel free to adapt to your path.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;{{ base_url }}&lt;/tt&gt; points to the base URL of your scripts. So, if they are all located under &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;http://aot.testing/dist/scripts/&lt;/span&gt;&lt;/tt&gt; that what you must use here.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;{{ version }}&lt;/tt&gt; is the current version of the code you are deploying so Rollbar can track your deploys and help you find the one that caused a problem.&lt;/li&gt;
&lt;li&gt;You also need the &lt;tt class="docutils literal"&gt;ROLLBAR_API_KEY&lt;/tt&gt; to be set and to contain your Rollbar server API key so you can authenticate to Rollbar.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/python3&lt;/span&gt;

&lt;span class="c1"&gt;# Copyright 2018, Julien Enselme, &amp;lt;jujens&amp;#64;jujens.eu&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)&lt;/span&gt;

&lt;span class="n"&gt;ANSIBLE_METADATA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'metadata_version'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'1.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'preview'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'supported_by'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'community'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;DOCUMENTATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'''
---
module: rollbar_source_maps
version_added: 1.0
author: &amp;quot;Julien Enselme (&amp;#64;Jenselme)&amp;quot;
short_description: Upload source maps to Rollbar
description:
- Upload source maps from a folder to Rollbar. We associate scripts and source maps thanks to the base URL and the name of the files. A source map must have the same name as the files and ends with .map
    (see https://docs.rollbar.com/docs/source-maps)
options:
token:
    description:
    - Your project access token.
    required: true
src:
    description:
    - The directory in which to look for source maps.
    required: true
base_url:
    description:
    - The base URL of your site so Rollbar can have the mapping of a file on the site to a file on the local system.
    required: true
version:
    description:
    - The version of the source maps.
    required: true
url:
    description:
    - Optional URL to submit the notification to.
    required: false
    default: 'https://api.rollbar.com/api/1/sourcemap'
validate_certs:
    description:
    - If C(no), SSL certificates for the target url will not be validated.
        This should only be used on personally controlled sites using
        self-signed certificates.
    required: false
    default: 'yes'
    choices: ['yes', 'no']
'''&lt;/span&gt;

&lt;span class="n"&gt;EXAMPLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'''
- name: Upload source maps to Rollbar
rollbar_source_maps:
    src: dist
    base_url: http://www.example.com/scripts/
    version: v1.0.0
    token: AAAA
'''&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;traceback&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urljoin&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ansible.module_utils.basic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AnsibleModule&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ansible.module_utils.six.moves.urllib.parse&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlencode&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ansible.module_utils._text&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;to_native&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ansible.module_utils.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fetch_url&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

    &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AnsibleModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;argument_spec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'https://api.rollbar.com/api/1/sourcemap'&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;validate_certs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'bool'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;supports_check_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'token'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'base_url'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'version'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'src'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'*.js.map'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;source_map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;source_map_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source_map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;minified_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urljoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.map'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'source_map'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;source_map_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s1"&gt;'access_token'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'token'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s1"&gt;'minified_url'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;minified_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'version'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fail_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Unable to upload source maps to Rollbar: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;to_native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format_exc&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fail_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'HTTP result code: &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt; connecting to &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt; with error &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Rollbar"></category><category term="Python"></category><category term="Ansible"></category></entry><entry><title>Timeout a function in python</title><link href="//www.jujens.eu/posts/en/2018/Jun/02/python-timeout-function/" rel="alternate"></link><published>2018-06-02T00:00:00+02:00</published><updated>2018-06-02T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-06-02:/posts/en/2018/Jun/02/python-timeout-function/</id><summary type="html">&lt;p&gt;You can use &lt;a class="reference external" href="https://docs.python.org/3.6/library/signal.html"&gt;signals&lt;/a&gt; and a context manager to acheive this. The idea is to register a function that will raise an exeption when the alarm signal is received and schedule the alarm signal for the timeout.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;signal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;contextlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;contextmanager&lt;/span&gt;


&lt;span class="nd"&gt;&amp;#64;contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Register a function …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;You can use &lt;a class="reference external" href="https://docs.python.org/3.6/library/signal.html"&gt;signals&lt;/a&gt; and a context manager to acheive this. The idea is to register a function that will raise an exeption when the alarm signal is received and schedule the alarm signal for the timeout.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;signal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;contextlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;contextmanager&lt;/span&gt;


&lt;span class="nd"&gt;&amp;#64;contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Register a function to raise a TimeoutError on the signal.&lt;/span&gt;
    &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGALRM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raise_timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Schedule the signal to be sent after ``time``.&lt;/span&gt;
    &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;alarm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Unregister the signal so it won't be triggered&lt;/span&gt;
        &lt;span class="c1"&gt;# if the timeout is not reached.&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGALRM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIG_IGN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;raise_timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;TimeoutError&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Add a timeout block.&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'entering block'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This should never get printed because the line before timed out'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Even if this solution works well, you can't nest &lt;tt class="docutils literal"&gt;timeout&lt;/tt&gt; which can be a problem. Perhaps a solution relying on &lt;a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html"&gt;concurrent.futures&lt;/a&gt; may work but during my tests, I never managed to correctly stop a function once a timeout has been reached.&lt;/p&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/a/494273/3900519"&gt;https://stackoverflow.com/a/494273/3900519&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category></entry><entry><title>Some tips for django</title><link href="//www.jujens.eu/posts/en/2018/May/21/django/" rel="alternate"></link><published>2018-05-21T00:00:00+02:00</published><updated>2018-05-21T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-05-21:/posts/en/2018/May/21/django/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#view-last-executed-query" id="id1"&gt;View last executed query&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#logging" id="id2"&gt;Logging&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#queries" id="id3"&gt;Queries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#migrations" id="id4"&gt;Migrations&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#checks" id="id5"&gt;Checks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#fake-all-pending-migrations" id="id6"&gt;Fake all pending migrations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#model-proxies" id="id7"&gt;Model proxies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#easily-increment-migrations-numbers" id="id8"&gt;Easily increment migrations numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-a-widget-with-custom-display" id="id9"&gt;Create a widget with custom display&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-a-nginx-reverse-proxy-in-dev" id="id10"&gt;Use a nginx reverse proxy in dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#checking-po-files" id="id11"&gt;Checking PO files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#testing" id="id12"&gt;Testing&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#inserting-pytest-fixtures-in-a-test-case" id="id13"&gt;Inserting pytest fixtures in a test case&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#reset-pk-sequence" id="id14"&gt;Reset PK sequence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#reset-factoryboy-sequence" id="id15"&gt;Reset factoryboy sequence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="view-last-executed-query"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;View …&lt;/a&gt;&lt;/h2&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#view-last-executed-query" id="id1"&gt;View last executed query&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#logging" id="id2"&gt;Logging&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#queries" id="id3"&gt;Queries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#migrations" id="id4"&gt;Migrations&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#checks" id="id5"&gt;Checks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#fake-all-pending-migrations" id="id6"&gt;Fake all pending migrations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#model-proxies" id="id7"&gt;Model proxies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#easily-increment-migrations-numbers" id="id8"&gt;Easily increment migrations numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-a-widget-with-custom-display" id="id9"&gt;Create a widget with custom display&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-a-nginx-reverse-proxy-in-dev" id="id10"&gt;Use a nginx reverse proxy in dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#checking-po-files" id="id11"&gt;Checking PO files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#testing" id="id12"&gt;Testing&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#inserting-pytest-fixtures-in-a-test-case" id="id13"&gt;Inserting pytest fixtures in a test case&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#reset-pk-sequence" id="id14"&gt;Reset PK sequence&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#reset-factoryboy-sequence" id="id15"&gt;Reset factoryboy sequence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="view-last-executed-query"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;View last executed query&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Run (the query will be as executed by the database with values correctly replaced and escaped):&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="logging"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Logging&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="queries"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Queries&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can configure your logger to view all requests made to the database with:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;LOGGING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
    &lt;span class="s1"&gt;'loggers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# ...&lt;/span&gt;
        &lt;span class="s1"&gt;'django.db'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s1"&gt;'handlers'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'console'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="s1"&gt;'level'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'DEBUG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://www.varrazzo.com/blog/2020/07/25/surviving-django/"&gt;Surviving Django (if you care about databases)&lt;/a&gt; under &lt;em&gt;Another random bit of advice&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="migrations"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Migrations&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="checks"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Checks&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can use this check to verify your migrations during CI (no dependency issue and no creation):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
python manage.py makemigrations
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;git status --porcelain &lt;span class="p"&gt;|&lt;/span&gt; grep migrations &lt;span class="p"&gt;|&lt;/span&gt; wc -l&lt;span class="k"&gt;)&lt;/span&gt; -gt &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'New migrations were created in the project. Please fix that.'&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you want to use it in a git hook, you should only consider untracked migrations:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
python manage.py migrate
&lt;span class="nv"&gt;migs_exit_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;migs_exit_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -ne &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;git status --porcelain &lt;span class="p"&gt;|&lt;/span&gt; grep migrations &lt;span class="p"&gt;|&lt;/span&gt; grep .py &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;'??'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; wc -l&lt;span class="k"&gt;)&lt;/span&gt; -gt &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'New migrations were created in the project. Please fix that.'&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="fake-all-pending-migrations"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Fake all pending migrations&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; -eu
&lt;span class="nb"&gt;set&lt;/span&gt; -o pipefail

&lt;span class="c1"&gt;# This will contain a list like this:
#wagtailusers
# [ ] 0001_initial
# [ ] 0002_add_verbose_name_on_userprofile
# [ ] 0003_add_verbose_names
# [ ] 0004_capitalizeverbose
# [ ] 0005_make_related_name_wagtail_specific
# [ ] 0006_userprofile_prefered_language
# [ ] 0007_userprofile_current_time_zone
# [ ] 0008_userprofile_avatar
# [ ] 0009_userprofile_verbose_name_plural
&lt;/span&gt;
&lt;span class="nv"&gt;pending_migrations&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;python manage.py showmigrations &lt;span class="p"&gt;|&lt;/span&gt; grep --color &lt;span class="s1"&gt;'\[ \]\|^[a-z]'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep --color &lt;span class="s1"&gt;'[  ]'&lt;/span&gt; -B &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;declare&lt;/span&gt; -A app_to_last_migration

&lt;span class="c1"&gt;# Make sure we loop over lines, not words.
&lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;$'\n'&lt;/span&gt;
&lt;span class="c1"&gt;# Array must not be quoted to correctly loop over each line.
# shellcheck disable=SC2068
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; line in &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pending_migrations&lt;/span&gt;&lt;span class="p"&gt;[&amp;#64;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="o"&gt;[&lt;/span&gt;a-z&lt;span class="o"&gt;]&lt;/span&gt;+ &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nv"&gt;app_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="se"&gt;\[&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="c1"&gt;# Capture the last migration of the app to pass it and all migrations before it.
&lt;/span&gt;        &lt;span class="nv"&gt;migration_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
        app_to_last_migration&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;app_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;migration_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; app_name in &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;!app_to_last_migration[&amp;#64;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    python manage.py migrate &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;app_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;app_to_last_migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;app_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; --fake
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="model-proxies"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Model proxies&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;They are useful to change the behavior of a model (based on a type column for instance) or to work on a subset of a table (based on a type column for instance). See &lt;a class="reference external" href="https://docs.djangoproject.com/en/2.1/topics/db/models/#proxy-models"&gt;the documentation&lt;/a&gt; for more details.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.db&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# ...&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderedPerson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ordering&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;last_name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="easily-increment-migrations-numbers"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id8"&gt;Easily increment migrations numbers&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a small bash script to increment the numbers of your migrations. Put it into your &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.profile&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.bashrc&lt;/span&gt;&lt;/tt&gt;. Use it like: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;inc-migrations&lt;/span&gt; PROJECT/apps/APP_NAME/migrations 0012&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;It will rename all migrations from 0012 (ie transform &lt;tt class="docutils literal"&gt;0012_mig.py&lt;/tt&gt; into &lt;tt class="docutils literal"&gt;0013_mig.py&lt;/tt&gt; and so on) and replace all occurrences of the previous name (eg &lt;tt class="docutils literal"&gt;0012_mig.py&lt;/tt&gt;) with the new one (eg &lt;tt class="docutils literal"&gt;0013_mig.py&lt;/tt&gt;).&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;function&lt;/span&gt; inc-migrations&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;local&lt;/span&gt; start_file
    &lt;span class="nb"&gt;local&lt;/span&gt; new_number
    &lt;span class="nb"&gt;local&lt;/span&gt; next_file

    &lt;span class="k"&gt;if&lt;/span&gt; ! &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;$&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -f &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d _ -f &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ls &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;* &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt; /dev/null&lt;span class="k"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; ! -f &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; doesn't exits&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
    &lt;span class="nb"&gt;let&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;new_number = &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; + 1&amp;quot;&lt;/span&gt;
    &lt;span class="nv"&gt;new_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;%04d\n&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;next_file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;ls &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;* &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt; /dev/null&lt;span class="k"&gt;)&lt;/span&gt;

    &lt;span class="nv"&gt;new_file_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_number&lt;/span&gt;&lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    git mv &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    sed -i &lt;span class="s2"&gt;&amp;quot;s/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;start_file&lt;/span&gt;&lt;span class="p"&gt;/.py/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;new_file_name&lt;/span&gt;&lt;span class="p"&gt;/.py/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/g&amp;quot;&lt;/span&gt; *.py

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -f &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;next_file&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        inc-migrations &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;next_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="create-a-widget-with-custom-display"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id9"&gt;Create a widget with custom display&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BonusTimeWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AdminIntegerFieldWidget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;UNITS_TO_TRANSLATIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'month'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ungettext_lazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;%(count)d&lt;/span&gt;&lt;span class="s1"&gt; month'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;%(count)d&lt;/span&gt;&lt;span class="s1"&gt; free months'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'month'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UNITS_TO_TRANSLATIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;supported_units&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UNITS_TO_TRANSLATIONS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; is not a supported unit. Supported units are: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;supported_units&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bonus_translation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UNITS_TO_TRANSLATIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Render the value in a custom span.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;

        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bonus_translation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'count'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mark_safe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;span&amp;gt;+ &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/span&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="use-a-nginx-reverse-proxy-in-dev"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id10"&gt;Use a nginx reverse proxy in dev&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The django web server works well but can be slow when it needs to handle many requests (to load many images for instance). One way to solve this is to use a production web server (nginx in this case) to handle most of the work (ie everything but dynamically generated pages).&lt;/p&gt;
&lt;p&gt;Prerequisites:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Install nginx&lt;/li&gt;
&lt;li&gt;Add the domain you want to use in your &lt;tt class="docutils literal"&gt;/etc/hosts&lt;/tt&gt; file. For instance &lt;tt class="docutils literal"&gt;127.0.0.1 myproject.localhost&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Make sure nginx has access to the files of your project. Most of the time a &lt;tt class="docutils literal"&gt;chmod 755 /PATH/TO/PROJECT&lt;/tt&gt; will do (repeat on each subdirectory nginx need to pass to access to your files). If you are using a shared computer, you may need to think about a more secure way to allow nginx to access the file (ACL may help you).&lt;/li&gt;
&lt;li&gt;If you are using SELinux, don't forget to add the proper context to the files. For instance, do something like:&lt;ol class="arabic"&gt;
&lt;li&gt;Add these files to the proper SELinux context by copying the one from the default web folder: &lt;tt class="docutils literal"&gt;semanage fcontext &lt;span class="pre"&gt;--add&lt;/span&gt; &lt;span class="pre"&gt;--equal&lt;/span&gt; /var/www/html /PATH/TO/PROJECT&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Restore the context of the files: &lt;tt class="docutils literal"&gt;restorecon &lt;span class="pre"&gt;-R&lt;/span&gt; /home/jenselme/Work/bureauxlocaux&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Check that the context is correct: &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-Z&lt;/span&gt;&lt;/tt&gt; The output should contain something like &lt;tt class="docutils literal"&gt;system_u:object_r:httpd_sys_content_t:s0&lt;/tt&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the nginx configuration to put in &lt;tt class="docutils literal"&gt;/etc/nginx/conf.d&lt;/tt&gt; (or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/nginx/sites-enabled&lt;/span&gt;&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# Make sure this host is in the ALLOWED_HOSTS variable in the settings.
&lt;/span&gt;    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;PROJECT.localhost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/PATH/TO/PROJECT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Prevent access to pyc and py files.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;.*\.pyc?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Search for files in the media folder. Change this if you configured Django to store your uploaded files elsewhere.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/files/(.*)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="s"&gt;/media/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Look for static files in the static folder or at the root of the project.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;^/static&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# Look both in the production static folder at the root of you project and in PROJECT
&lt;/span&gt;        &lt;span class="c1"&gt;# (where you have the apps directory and the static directory you use in dev).
&lt;/span&gt;        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="s"&gt;/PROJECT/&lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Relay everything else to the django web server.
&lt;/span&gt;    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To add a connect timeout (eg to mimic Heroku's timeout) to the Django dev server, add the lines below in the &lt;tt class="docutils literal"&gt;&amp;#64;django&lt;/tt&gt; block:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;proxy_connect_timeout&lt;/span&gt;   &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_send_timeout&lt;/span&gt;      &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;proxy_read_timeout&lt;/span&gt;      &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;send_timeout&lt;/span&gt;            &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="checking-po-files"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id11"&gt;Checking PO files&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env bash
&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; -eu

&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  msgfmt -v --check &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="testing"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id12"&gt;Testing&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="inserting-pytest-fixtures-in-a-test-case"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id13"&gt;Inserting pytest fixtures in a test case&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpamTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="nd"&gt;&amp;#64;pytest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autouse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inject_fixtures&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;caplog&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_caplog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;caplog&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_eggs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_caplog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at_level&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;spam&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eggs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_caplog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'bacon'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/a/50375022"&gt;https://stackoverflow.com/a/50375022&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reset-pk-sequence"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id14"&gt;Reset PK sequence&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reset_database_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;models_or_factories&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;model_or_factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model_or_factory&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;models_or_factories&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;sequence_sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sequence_reset_sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no_style&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sequence_sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/a/50275965/3900519"&gt;https://stackoverflow.com/a/50275965/3900519&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reset-factoryboy-sequence"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id15"&gt;Reset factoryboy sequence&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reset_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;factories&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;reset_database_sequences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;factories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;factory_cls&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;factories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;factory_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_sequence&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category><category term="Web"></category><category term="Django"></category></entry><entry><title>JavaScript tips</title><link href="//www.jujens.eu/posts/en/2018/Mar/07/javascript/" rel="alternate"></link><published>2018-03-07T00:00:00+01:00</published><updated>2018-03-07T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-03-07:/posts/en/2018/Mar/07/javascript/</id><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#normalize-an-utf-8-string" id="id1"&gt;Normalize an UTF-8 string&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="normalize-an-utf-8-string"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Normalize an UTF-8 string&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Rely on &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize"&gt;String.prototype.normalize()&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Crème Brulée&amp;quot;&lt;/span&gt;
&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NFD'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/[\u0300-\u036f]/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Creme Brulee'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463#37511463"&gt;https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463#37511463&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="JavaScript"></category></entry><entry><title>PostgreSQL tips</title><link href="//www.jujens.eu/posts/en/2018/Mar/07/postgresq/" rel="alternate"></link><published>2018-03-07T00:00:00+01:00</published><updated>2018-03-07T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-03-07:/posts/en/2018/Mar/07/postgresq/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#update-fields-in-jsonb-format" id="id1"&gt;Update fields in JSONB format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#csv-export-import" id="id2"&gt;CSV export/import&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#update-rows-in-bulks" id="id3"&gt;Update rows in bulks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#understand-lock-issues" id="id4"&gt;Understand lock issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-variables-in-query" id="id5"&gt;Use variables in query&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#database-sizes" id="id6"&gt;Database sizes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="update-fields-in-jsonb-format"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Update fields in JSONB format&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use the &lt;tt class="docutils literal"&gt;jsonb_set(COLUMN_NAME, PATH_TO_CHANGE, VALUE)&lt;/tt&gt; function. The value must be a valid value in JSON (ie use &lt;tt class="docutils literal"&gt;'500'&lt;/tt&gt; for numbers, &lt;tt class="docutils literal"&gt;'true'&lt;/tt&gt; for …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#update-fields-in-jsonb-format" id="id1"&gt;Update fields in JSONB format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#csv-export-import" id="id2"&gt;CSV export/import&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#update-rows-in-bulks" id="id3"&gt;Update rows in bulks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#understand-lock-issues" id="id4"&gt;Understand lock issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-variables-in-query" id="id5"&gt;Use variables in query&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#database-sizes" id="id6"&gt;Database sizes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="update-fields-in-jsonb-format"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Update fields in JSONB format&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use the &lt;tt class="docutils literal"&gt;jsonb_set(COLUMN_NAME, PATH_TO_CHANGE, VALUE)&lt;/tt&gt; function. The value must be a valid value in JSON (ie use &lt;tt class="docutils literal"&gt;'500'&lt;/tt&gt; for numbers, &lt;tt class="docutils literal"&gt;'true'&lt;/tt&gt; for boolean and &lt;tt class="docutils literal"&gt;'&amp;quot;str&amp;quot;'&lt;/tt&gt; for strings). Examples:&lt;/p&gt;
&lt;pre class="code SQL literal-block"&gt;
&lt;span class="c1"&gt;-- Set the postcode field to the 92600 integer.
&lt;/span&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;sales&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonb_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{postcode}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'92600'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;47880&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Set a nested field to the &amp;quot;FRA&amp;quot; value. Note: the nested object must exists.
&lt;/span&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;sales&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonb_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{country,code}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;quot;FRA&amp;quot;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;-- Set a value at a given position in an array (an object must exist at this position).
&lt;/span&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;sales&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;phones&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jsonb_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phones&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{0,number}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;quot;06&amp;quot;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="csv-export-import"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;CSV export/import&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To export content of a table to a CSV file (eg to re-import it in a different database on a different server). Update the query and connection options to fit your needs:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
psql -U user -c &lt;span class="s1"&gt;'COPY (SELECT * FROM sales WHERE id = 110683) To STDOUT WITH CSV HEADER;'&lt;/span&gt; database &amp;gt; /tmp/sales.csv
&lt;/pre&gt;
&lt;p&gt;To import the data from a CSV file, you need to specify the columns you want to import. To find them, run &lt;tt class="docutils literal"&gt;head &lt;span class="pre"&gt;-n&lt;/span&gt; 1 /tmp/sales.csv&lt;/tt&gt; to get the first lines of the CSV which contains the headers. You can then run the command below.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
psql -U user database -c &lt;span class="s2"&gt;&amp;quot;COPY sales(id,organization_id,date,name,address) FROM STDIN WITH CSV HEADER;&amp;quot;&lt;/span&gt; &amp;lt; /tmp/sales.csv
&lt;/pre&gt;
&lt;p&gt;Note 1: it should be possible to import the data with &lt;tt class="docutils literal"&gt;psql &lt;span class="pre"&gt;-U&lt;/span&gt; user database &lt;span class="pre"&gt;-c&lt;/span&gt; &amp;quot;COPY sales(id,organization_id,date,name,address) FROM '/tmp/sales.csv' WITH CSV HEADER;&amp;quot;&lt;/tt&gt;. However, when I tried that, I got: &lt;tt class="docutils literal"&gt;ERROR:&amp;nbsp; could not open file &amp;quot;/tmp/sale.csv&amp;quot; for reading: No such file or directory&lt;/tt&gt; even though the file existed.&lt;/p&gt;
&lt;p&gt;Note 2: you can also achieve this with pgAdmin with you want a nice GUI.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="update-rows-in-bulks"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Update rows in bulks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This will update rows by batch of 100 without being blocked by locks. It is useful to prepare for the addition of an &lt;tt class="docutils literal"&gt;NOT NULL&lt;/tt&gt; constraint without downtime.&lt;/p&gt;
&lt;pre class="code SQL literal-block"&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;server_info&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt;    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt;  &lt;span class="n"&gt;server_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;server_ip&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt;   &lt;span class="n"&gt;server_info&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt;  &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'standby'&lt;/span&gt;
    &lt;span class="k"&gt;LIMIT&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="k"&gt;FOR&lt;/span&gt;    &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;SKIP&lt;/span&gt; &lt;span class="n"&gt;LOCKED&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="understand-lock-issues"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Understand lock issues&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This will display all queries blocked by locks and which query is blocking them (pg 9.6+):&lt;/p&gt;
&lt;pre class="code SQL literal-block"&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;usename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pg_blocking_pids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;blocked_by&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;query_start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;blocked_query&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_stat_activity&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="n"&gt;NULLS&lt;/span&gt; &lt;span class="k"&gt;LAST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/a/43363536"&gt;https://stackoverflow.com/a/43363536&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="use-variables-in-query"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Use variables in query&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use a CTE:&lt;/p&gt;
&lt;pre class="code SQL literal-block"&gt;
&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;myconstants&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;values&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;somewhere&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;myconstants&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myconstants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;var1&lt;/span&gt;
&lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="n"&gt;something_else&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;myconstants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;var2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/a/54220318/3900519"&gt;https://stackoverflow.com/a/54220318/3900519&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="database-sizes"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Database sizes&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To view the size of tables in a database:&lt;/p&gt;
&lt;pre class="code SQL literal-block"&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;nspname&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;relname&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;relation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;pg_size_pretty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_total_relation_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="ss"&gt;&amp;quot;total_size&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_class&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;pg_namespace&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relnamespace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;nspname&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pg_catalog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'information_schema'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relkind&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'i'&lt;/span&gt;
    &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;nspname&lt;/span&gt; &lt;span class="o"&gt;!~&lt;/span&gt; &lt;span class="s1"&gt;'^pg_toast'&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;pg_total_relation_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;oid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To view the sizes of databases:&lt;/p&gt;
&lt;pre class="code SQL literal-block"&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;pg_database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;pg_size_pretty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_database_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;size&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pg_database&lt;/span&gt;
  &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;size&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="http://www.postgresqltutorial.com/postgresql-database-indexes-table-size/"&gt;http://www.postgresqltutorial.com/postgresql-database-indexes-table-size/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="PostgreSQL"></category><category term="Database"></category><category term="SQL"></category></entry><entry><title>Run multiple docker daemons on the same host</title><link href="//www.jujens.eu/posts/en/2018/Feb/25/multiple-docker/" rel="alternate"></link><published>2018-02-25T00:00:00+01:00</published><updated>2018-02-25T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2018-02-25:/posts/en/2018/Feb/25/multiple-docker/</id><summary type="html">&lt;p&gt;Today I am going to explain how you can run multiple docker daemons on the same host. This can be useful if you want several users to use docker and want each of them to be isolated from one another (ie don't see images, containers, … of other users). The solution …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I am going to explain how you can run multiple docker daemons on the same host. This can be useful if you want several users to use docker and want each of them to be isolated from one another (ie don't see images, containers, … of other users). The solution relies on user namespaces &lt;a class="footnote-reference" href="#userns" id="id1"&gt;[1]&lt;/a&gt; and sudo.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-sudo" id="id2"&gt;Configure sudo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-username-spaces" id="id3"&gt;Configure username spaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#docker-unit-file" id="id4"&gt;Docker unit file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#usage" id="id5"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#docker-compose" id="id6"&gt;docker-compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id7"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="configure-sudo"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Configure sudo&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, we will update the sudoers file by launching &lt;tt class="docutils literal"&gt;visudo&lt;/tt&gt; to allow the users to use the docker command and force them to use the proper daemon. To do that, append the following lines at the end of the file:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
USER ALL=(root) NOPASSWD: /usr/bin/docker -H unix\:///var/run/docker-USER.sock *, ! /usr/bin/docker *--priviledged*, ! /usr/bin/docker *host*
&lt;/pre&gt;
&lt;p&gt;You must replace &lt;tt class="docutils literal"&gt;USER&lt;/tt&gt; (present two times) by the username of the user you want to allow (you must duplicate the line for each user you want to allow). This will allow USER to launch the docker command as root, without a password, while restricting the user to use its docker instance by talking to the proper socket. We also prevent the user to run a command that contains the priviledged option and host keyword. This is meant to avoid them disabling namespaces for security reasons. If we don't, they could run containers as true root on the machine. This would make our isolation less useful. If you don't care about that, you can simply use:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
USER ALL=(root) NOPASSWD: /usr/bin/docker -H unix\:///var/run/docker-USER.sock *
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="configure-username-spaces"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Configure username spaces&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Edit &lt;tt class="docutils literal"&gt;/etc/subuid&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;/etc/subgid&lt;/tt&gt; so you have two lines per users which will look like (depending on your system, you may already have the second line):&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
USER:USERID:1
USER:1XXXXX:65536
&lt;/pre&gt;
&lt;p&gt;The first line is used to map the user of id 1 in the container (ie root) to the id of a normal user outside. The second line, defines which uid will be used to map other users: the first number gives the first id and the second the number of ids. The ranges must not collide between users. Since this is still probably obscure, let me give an example:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;I have a user named &lt;tt class="docutils literal"&gt;jenselme&lt;/tt&gt;. It has uid 1000 on the system.&lt;/li&gt;
&lt;li&gt;I have a user named &lt;tt class="docutils literal"&gt;julien&lt;/tt&gt;. It has uid 1001 on the system.&lt;/li&gt;
&lt;li&gt;To enable mapping of root in the container to jenselme on the host for jenselme's containers, I add &lt;tt class="docutils literal"&gt;jenselme:1000:1&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;/etc/subuid&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;/etc/subgid&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;To enable mapping of other users in jenselme's containers, I add: &lt;tt class="docutils literal"&gt;jenselme:100000:65536&lt;/tt&gt;. So users will be dispatched to host uids between 100000 and 165535. For instance, user with id 33 in a container will have id 100032 on the host (id mapping starts at 100000, hence 100032 and not 100033).&lt;/li&gt;
&lt;li&gt;To enable mapping of root in the container to julien on the host for julien's containers, I add &lt;tt class="docutils literal"&gt;julien:1001:1&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;/etc/subuid&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;/etc/subgid&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;To enable mapping of other users in julien's containers, I add: &lt;tt class="docutils literal"&gt;julien:165536:65536&lt;/tt&gt;. So users will be dispatched to host uids between 165536 and 231071. Which are the 65536 ids avaiable after jenselme's ids range.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So my files will contain:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
jenselme:1000:1
jenselme:100000:65536
julien:1001:1
julien:165536:65536
&lt;/pre&gt;
&lt;p&gt;To learn more about this, you can read &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/"&gt;my article dedicated to this subject&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="docker-unit-file"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Docker unit file&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To do that, you first need to create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker&amp;#64;.service&lt;/span&gt;&lt;/tt&gt; file so you can select for which user you want to run docker. This file must be located under &lt;tt class="docutils literal"&gt;/etc/systemd/system/&lt;/tt&gt; and have this content:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Docker Application Container Engine&lt;/span&gt;
&lt;span class="na"&gt;Documentation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;http://docs.docker.com&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target docker-containerd.service&lt;/span&gt;
&lt;span class="na"&gt;Wants&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;docker-storage-setup.service&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;docker-containerd.service rhel-push-plugin.socket registries.service&lt;/span&gt;

&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;notify&lt;/span&gt;
&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/run/containers/registries.conf&lt;/span&gt;
&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;-/etc/sysconfig/docker&lt;/span&gt;
&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;-/etc/sysconfig/docker-storage&lt;/span&gt;
&lt;span class="na"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;-/etc/sysconfig/docker-network&lt;/span&gt;
&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;GOTRACEBACK=crash&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/dockerd-current \
          --add-runtime oci=/usr/libexec/docker/docker-runc-current \
          --default-runtime=oci \
          --authorization-plugin=rhel-push-plugin \
          --containerd /run/containerd.sock \
          --exec-opt native.cgroupdriver=systemd \
          --userland-proxy-path=/usr/libexec/docker/docker-proxy-current \
          --init-path=/usr/libexec/docker/docker-init-current \
          --seccomp-profile=/etc/docker/seccomp.json \
          --userns-remap %i \
          --host unix:///var/run/docker-%i.sock \
          --pidfile /var/run/docker-%i.pid \
          $OPTIONS \
          $DOCKER_STORAGE_OPTIONS \
          $DOCKER_NETWORK_OPTIONS \
          $ADD_REGISTRY \
          $BLOCK_REGISTRY \
          $INSECURE_REGISTRY \
          $REGISTRIES&lt;/span&gt;
&lt;span class="na"&gt;ExecReload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/bin/kill -s HUP $MAINPID&lt;/span&gt;
&lt;span class="na"&gt;TasksMax&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8192&lt;/span&gt;
&lt;span class="na"&gt;LimitNOFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1048576&lt;/span&gt;
&lt;span class="na"&gt;LimitNPROC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;1048576&lt;/span&gt;
&lt;span class="na"&gt;LimitCORE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;infinity&lt;/span&gt;
&lt;span class="na"&gt;TimeoutStartSec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;Restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-abnormal&lt;/span&gt;

&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I added three command line options to the standard service. The &lt;tt class="docutils literal"&gt;%i&lt;/tt&gt; will be replace by what comes after the &lt;tt class="docutils literal"&gt;&amp;#64;&lt;/tt&gt; when we will run docker (eg USER with &lt;tt class="docutils literal"&gt;systemctl start docker&amp;#64;USER.service&lt;/tt&gt;). Let me detail the new options:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--userns-remap&lt;/span&gt; %i&lt;/tt&gt;: enables the username space for the user. This way, each users won't be able to see/use the images and containers of each other: when usermapping is enabled, docker keeps everything (images, containers, networks, volume …) separate for each mapping.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--host&lt;/span&gt; &lt;span class="pre"&gt;unix:///var/run/docker-%i.sock&lt;/span&gt;&lt;/tt&gt;: change the name of the socket to listen to. If we don't do this, all our instances would try to listen to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;unix:///var/run/docker.sock&lt;/span&gt;&lt;/tt&gt; which wouldn't work.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--pidfile&lt;/span&gt; &lt;span class="pre"&gt;/var/run/docker-%i.pid&lt;/span&gt;&lt;/tt&gt;: change the name of the PID file of the process. If we don't do this, all our instances would try to use &lt;tt class="docutils literal"&gt;/var/run/docker.pid&lt;/tt&gt; which wouldn't work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to use a different docker configuration file for each instance, you can add &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--config-file&lt;/span&gt; &lt;span class="pre"&gt;/etc/docker/daemon-%i.json&lt;/span&gt;&lt;/tt&gt; to the list of option. This will make docker use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/docker/daemon-USER.json&lt;/span&gt;&lt;/tt&gt; as a config file when running &lt;tt class="docutils literal"&gt;docker&amp;#64;USER&lt;/tt&gt;. &lt;strong&gt;Note:&lt;/strong&gt; the file must exist and be valid JSON, otherwise, docker won't start.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I have commented the part that differs from the standard &lt;tt class="docutils literal"&gt;docker.service&lt;/tt&gt; on fedora. If you use a different distribution, the content of this file may differ but you should be able to adapt it from mine. If you have a question, please leave a comment.&lt;/p&gt;
&lt;p&gt;Don't forget to make systemd take the new file into account with &lt;tt class="docutils literal"&gt;systemctl &lt;span class="pre"&gt;daemon-reload&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="usage"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Usage&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, everything is functional, you can start your daemons with &lt;tt class="docutils literal"&gt;systemctl start docker&amp;#64;USER.service&lt;/tt&gt;. To use a daemon, you need to specify to docker which socket to use with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-H&lt;/span&gt;&lt;/tt&gt; option like this: &lt;tt class="docutils literal"&gt;sudo docker &lt;span class="pre"&gt;-H&lt;/span&gt; &lt;span class="pre"&gt;unix:///var/run/docker-USER.sock&lt;/span&gt;&lt;/tt&gt;. To ease the process, you can create an alias like this in your &lt;tt class="docutils literal"&gt;.bashrc&lt;/tt&gt; file (adapt to your shell):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;sudo docker -H unix:///var/run/docker-&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;whoami&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.sock&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;After opening a new shell or doing &lt;tt class="docutils literal"&gt;source &lt;span class="pre"&gt;~/.bashrc&lt;/span&gt;&lt;/tt&gt;, you can use the docker command directly, eg:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
docker run --rm busybox ls
&lt;/pre&gt;
&lt;p&gt;I suggest you play around with it on multiple accounts to see how all of this works before read the end of the article.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="docker-compose"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;docker-compose&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can use docker-compose like this &lt;tt class="docutils literal"&gt;sudo &lt;span class="pre"&gt;docker-compose&lt;/span&gt; &lt;span class="pre"&gt;-H&lt;/span&gt; &lt;span class="pre"&gt;unix:///var/run/docker-$(whoami).sock&lt;/span&gt;&lt;/tt&gt; if you add the line below to you sudoers:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
USER ALL=(root) NOPASSWD: /usr/bin/docker-compose -H unix:///var/run/docker-USER.sock *
&lt;/pre&gt;
&lt;p&gt;However, since docker compose does HTTP request to your docker socket, you cannot rely on sudo to prevent the user from launching priviledged or unamespaced containers. You will need an &lt;a class="reference external" href="https://docs.docker.com/engine/extend/plugins_authorization/"&gt;authorization plugin&lt;/a&gt; for that like &lt;a class="reference external" href="https://github.com/kassisol/hbm"&gt;HBM&lt;/a&gt; or &lt;a class="reference external" href="https://github.com/twistlock/authz"&gt;Twistlock AuthZ Broker&lt;/a&gt;. &lt;strong&gt;Note:&lt;/strong&gt; I have not tested these plugins.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Everything should be working and you should be able to run as many docker daemons as you need. I hope I was clear on this quite technical subject. If I wasn't or if you just want to leave a remark, please leave a comment below!&lt;/p&gt;
&lt;table class="docutils footnote" frame="void" id="userns" rules="none"&gt;
&lt;colgroup&gt;&lt;col class="label" /&gt;&lt;col /&gt;&lt;/colgroup&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td class="label"&gt;&lt;a class="fn-backref" href="#id1"&gt;[1]&lt;/a&gt;&lt;/td&gt;&lt;td&gt;User namespaces allow to differentiate user ids inside the container from user ids outside. For instance root (ie uid 1) in the container will be a standard user outside of it (eg uid 1000). To learn more about user namespaces and their usage with docker, read &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/"&gt;this article&lt;/a&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="Docker"></category><category term="Linux"></category></entry><entry><title>Can we clean password from PHP memory?</title><link href="//www.jujens.eu/posts/en/2017/Nov/26/php-clean-password-tests/" rel="alternate"></link><published>2017-11-26T00:00:00+01:00</published><updated>2017-11-26T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-11-26:/posts/en/2017/Nov/26/php-clean-password-tests/</id><summary type="html">&lt;p&gt;At work in a PHP application, we rely on &lt;a class="reference external" href="https://github.com/jedisct1/libsodium-php"&gt;libsodium&lt;/a&gt; to erase a password from &lt;tt class="docutils literal"&gt;$_POST&lt;/tt&gt;. It may sound like a good idea: once the password is not in memory any more, it can't leak. But the question is: is it really erased from memory? That's the question will answer …&lt;/p&gt;</summary><content type="html">&lt;p&gt;At work in a PHP application, we rely on &lt;a class="reference external" href="https://github.com/jedisct1/libsodium-php"&gt;libsodium&lt;/a&gt; to erase a password from &lt;tt class="docutils literal"&gt;$_POST&lt;/tt&gt;. It may sound like a good idea: once the password is not in memory any more, it can't leak. But the question is: is it really erased from memory? That's the question will answer here.&lt;/p&gt;
&lt;p&gt;To do this, we will create a docker container with PHP script to check this. We will dump the memory of the process into a file and we will inspect this file to see if the password is in it.&lt;/p&gt;
&lt;p&gt;You can the scripts and the Dockerfile &lt;a class="reference external" href="/static/php-clean-password-tests/php-clean-password-tests.zip"&gt;here&lt;/a&gt; if you want to run all tests by yourself.&lt;/p&gt;
&lt;p&gt;First, let's look at the Dockerfile:&lt;/p&gt;
&lt;pre class="code Docker literal-block"&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="s"&gt;php:7.1-apache&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt; *.php /var/www/html/

&lt;span class="c"&gt;# Install libsodium&lt;/span&gt;
&lt;span class="k"&gt;RUN&lt;/span&gt; apt-get update &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get install build-essential -y &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl -fsSL &lt;span class="s1"&gt;'https://github.com/jedisct1/libsodium/releases/download/1.0.11/libsodium-1.0.11.tar.gz'&lt;/span&gt; -o libsodium.tar.gz &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mkdir -p libsodium &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; tar -xf libsodium.tar.gz -C libsodium --strip-components&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm libsodium.tar.gz &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; libsodium &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./configure &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make check &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; make install &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rm -r libsodium
&lt;span class="k"&gt;RUN&lt;/span&gt; pecl install libsodium-1.0.6 &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-enable libsodium

&lt;span class="c"&gt;# Install packages to dump memory and inspect the dump&lt;/span&gt;
&lt;span class="k"&gt;RUN&lt;/span&gt; apt-get install -y gdb

&lt;span class="k"&gt;RUN&lt;/span&gt; rm -rf /var/lib/apt/lists/*
&lt;/pre&gt;
&lt;p&gt;Nothing fancy: we start from an image that include Apache and PHP 7.1. We then install libsodium to erase the memory and gdb to have tools to dump the memory and analyse the dump.&lt;/p&gt;
&lt;p&gt;Now the scripts. I made 2. The first &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;check-post.php&lt;/span&gt;&lt;/tt&gt; is meant to check that the value in &lt;tt class="docutils literal"&gt;$_POST&lt;/tt&gt; is correctly erased:&lt;/p&gt;
&lt;pre class="code php literal-block"&gt;
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="c1"&gt;// Before clean
&lt;/span&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Sodium\memzero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// After clean.
&lt;/span&gt;&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The second is meant to dump the memory of the process: we erase the memory then run an infinite loop so we have time to dump the memory of the process:&lt;/p&gt;
&lt;pre class="code php literal-block"&gt;
&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="nx"&gt;Sodium\memzero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I didn't do &lt;tt class="docutils literal"&gt;var_dump&lt;/tt&gt; in this one to be sure the password won't be in memory somewhere.&lt;/p&gt;
&lt;p&gt;Let's build the image: &lt;tt class="docutils literal"&gt;docker build &lt;span class="pre"&gt;-t&lt;/span&gt; &lt;span class="pre"&gt;php-clean-password-tests&lt;/span&gt; .&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Let's run it with &lt;tt class="docutils literal"&gt;docker run &lt;span class="pre"&gt;-d&lt;/span&gt; &lt;span class="pre"&gt;--name&lt;/span&gt; &lt;span class="pre"&gt;php-clean-password-tests&lt;/span&gt; &lt;span class="pre"&gt;-p&lt;/span&gt; 8080:80 &lt;span class="pre"&gt;php-clean-password-tests&lt;/span&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; if you use user namespaces, you must start the container with &lt;tt class="docutils literal"&gt;docker run &lt;span class="pre"&gt;-d&lt;/span&gt; &lt;span class="pre"&gt;--name&lt;/span&gt; &lt;span class="pre"&gt;php-clean-password-tests&lt;/span&gt; &lt;span class="pre"&gt;-p&lt;/span&gt; 8080:80 &lt;span class="pre"&gt;--userns=host&lt;/span&gt; &lt;span class="pre"&gt;--privileged&lt;/span&gt; &lt;span class="pre"&gt;php-clean-password-tests&lt;/span&gt;&lt;/tt&gt; instead, because you need to be the true root to dump the memory of a process.&lt;/p&gt;
&lt;p&gt;Let's tests the first script with &lt;a class="reference external" href="https://httpie.org/"&gt;httpie&lt;/a&gt; or good old &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
http -f POST localhost:8080/check-post.php &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;superpasswd
curl -X POST -d &lt;span class="s1"&gt;'password=superpasswd'&lt;/span&gt; localhost:8080/check-post.php
&lt;/pre&gt;
&lt;p&gt;We have this output (with httpie):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 81
Content-Type: text/html; charset=UTF-8
Date: Sun, 26 Nov 2017 10:00:07 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.10 (Debian)
Vary: Accept-Encoding
X-Powered-By: PHP/7.1.11

array(1) {
[&amp;quot;password&amp;quot;]=&amp;gt;
string(11) &amp;quot;superpasswd&amp;quot;
}
array(1) {
[&amp;quot;password&amp;quot;]=&amp;gt;
NULL
}
&lt;/pre&gt;
&lt;p&gt;So far so good! Before running the second script, let's enter in the container with: &lt;tt class="docutils literal"&gt;docker exec &lt;span class="pre"&gt;-it&lt;/span&gt; &lt;span class="pre"&gt;php-clean-password-tests&lt;/span&gt; /bin/bash&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Run &lt;tt class="docutils literal"&gt;http &lt;span class="pre"&gt;-f&lt;/span&gt; POST &lt;span class="pre"&gt;localhost:8080/wait-memory-dump.php&lt;/span&gt; password=superpasswd&lt;/tt&gt; in your host shell to launch the second script.&lt;/p&gt;
&lt;p&gt;In the container, run &lt;tt class="docutils literal"&gt;ps aux&lt;/tt&gt; to list all running processes. You should see an &lt;tt class="docutils literal"&gt;apache2&lt;/tt&gt; command with non zero time, like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
www-data    17  9.5  0.0 173156 11916 ?        R    10:10   0:02 apache2 -DFOREGROUND
&lt;/pre&gt;
&lt;p&gt;That's the process running our script. Get the PID (first number from the left, &lt;em&gt;17&lt;/em&gt; in this example) and dump the memory with:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
gcore 17  # Replace 17 by the PID you got before
&lt;/pre&gt;
&lt;p&gt;You should now have a file named like &lt;tt class="docutils literal"&gt;core.17&lt;/tt&gt; in the current directory. This is a binary file we could inspect directly with &lt;tt class="docutils literal"&gt;gdb&lt;/tt&gt; but to keep things simple, we will convert it to text with &lt;tt class="docutils literal"&gt;objdump&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
objdump -s core.17 &amp;gt; core.17.txt
&lt;/pre&gt;
&lt;p&gt;Now, let's &lt;tt class="docutils literal"&gt;grep&lt;/tt&gt; for our password:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
grep pass core.17.txt
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; given how the file is structured, search direcly for a long string won't work. Try breaking your password into sequence of 3/4 characters to find it.&lt;/p&gt;
&lt;p&gt;Here is the result (excerpt):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
563aaa079c90 67696e5f 73686132 35365f70 61737377  gin_sha256_passw
7fd64d457030 70617373 776f7264 3d737570 65727061  password=superpa
7fd64d45d090 70617373 776f7264 00000000 00000000  password........
(…)
7ffd7df771b0 70617373 776f7264 3d737570 65727061  password=superpa
7ffd7df78e50 70617373 776f7264 0826f252 d67f0000  password.&amp;amp;.R....
7ffd7df79050 70617373 776f7264 3d737570 65727061  password=superpa
&lt;/pre&gt;
&lt;p&gt;Conclusion: the password is still in memory. So it can still leak and the &lt;tt class="docutils literal"&gt;memzero&lt;/tt&gt; wasn't that useful (you wouldn't output the password from &lt;tt class="docutils literal"&gt;$_POST&lt;/tt&gt; anywhere anyway, right?). Where can it come from? Since the script are deliberately small, I suspect it comes from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;php://input&lt;/span&gt;&lt;/tt&gt; a virtual, read only file where PHP stores the raw input of the request. You can read it with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;file_get_contents('php://input')&lt;/span&gt;&lt;/tt&gt; and as far as I know, you can't erase it with &lt;tt class="docutils literal"&gt;memzero&lt;/tt&gt;. Now imagine a true application: you validate the password? Are you sure it is not copied somewhere by your validation code? You use an ORM? Did it copy it somewhere for its internal usage? I guess that to be sure the password is just present in one place and erase it correctly from that one place is a herculean thing to do.&lt;/p&gt;
&lt;p&gt;Last question: does it matter? From my point of view no. In modern web development, we don't manage the memory ourselves which makes the risk of leaking it by accident very low (unlike in C if you recall the heartbleed vulnerability). Which means, if you make sure your application core dumps (memory dump generated in cases of same application crash) are disable or not accessible from the outside, you are good. And between you and me, if an attacker can dump memory of a process, (s)he is root on your server, so your security sucks. Period.&lt;/p&gt;
&lt;p&gt;So I don't think your application will gain much security if you do try to clean password from memory yourself (and you probably can't do it anyway or at least not without breaking promises from your programming language). The only thing it may do is give you a false sense of security. This doesn't meant you should stick to good password related practices:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Hash them with algorithms designed to hash passwords like bcryt or argon2 (and not sha related algorithm or worst md5).&lt;/li&gt;
&lt;li&gt;Slat them.&lt;/li&gt;
&lt;li&gt;Don't load the hash from the database unless you need it.&lt;/li&gt;
&lt;li&gt;Don't put &lt;a class="reference external" href="https://www.troyhunt.com/3-reasons-youre-forced-into-creating/"&gt;silly restrictions&lt;/a&gt; on the password content or length (but check that it is strong).&lt;/li&gt;
&lt;li&gt;Protect yourself against &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Cross-site_scripting"&gt;XSS&lt;/a&gt; and &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Cross-site_request_forgery"&gt;CRSF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Secure you servers and &lt;a class="reference external" href="https://securityintelligence.com/news/mongodb-databases-may-be-exposed-by-security-misconfigurations/"&gt;databases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further reading:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.sjoerdlangkemper.nl/2016/05/22/should-passwords-be-cleared-from-memory/"&gt;Clearing secrets from memory&lt;/a&gt;: an article that explains how hard it is to clean memory.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.sjoerdlangkemper.nl/2016/06/09/clearing-memory-in-python/"&gt;Clearing memory in Python&lt;/a&gt;: an article by the same person explaining how you could do it in Python and the problem you might get because of that.&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Programmation"></category><category term="php"></category><category term="Docker"></category><category term="security"></category></entry><entry><title>How to cache Python module in Gitlab CI</title><link href="//www.jujens.eu/posts/en/2017/Aug/20/gitlabci-python-cache/" rel="alternate"></link><published>2017-08-20T00:00:00+02:00</published><updated>2017-08-20T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-20:/posts/en/2017/Aug/20/gitlabci-python-cache/</id><summary type="html">&lt;p&gt;By default, pip cache will be in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.pip&lt;/span&gt;&lt;/tt&gt;. However, this folder cannot be cached by Gitlab. The trick is to force pip to use a folder located in the build directory with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--cache-dir&lt;/span&gt;&lt;/tt&gt; option. You can then cache this folder.&lt;/p&gt;
&lt;p&gt;For instance, you can use &lt;tt class="docutils literal"&gt;.pip&lt;/tt&gt; as in the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;By default, pip cache will be in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.pip&lt;/span&gt;&lt;/tt&gt;. However, this folder cannot be cached by Gitlab. The trick is to force pip to use a folder located in the build directory with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--cache-dir&lt;/span&gt;&lt;/tt&gt; option. You can then cache this folder.&lt;/p&gt;
&lt;p&gt;For instance, you can use &lt;tt class="docutils literal"&gt;.pip&lt;/tt&gt; as in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.gitlab-ci.yml&lt;/span&gt;&lt;/tt&gt; excerpt below:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;python:3.6&lt;/span&gt;

&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;.pip&lt;/span&gt;

&lt;span class="nt"&gt;before_script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;mkdir -p .pip&lt;/span&gt;
  &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;pip install -U pip&lt;/span&gt;
  &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;pip --cache-dir=.pip install -r requires.txt&lt;/span&gt;
  &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;pip --cache-dir=.pip install -r tests_requires.txt&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="gitlab"></category><category term="ci"></category><category term="Python"></category></entry><entry><title>nginx tips</title><link href="//www.jujens.eu/posts/2017/Aug/19/nginx-tips/" rel="alternate"></link><published>2017-08-19T00:00:00+02:00</published><updated>2017-08-19T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-19:/posts/2017/Aug/19/nginx-tips/</id><content type="html">&lt;div class="section" id="cors-for-multiple-domains"&gt;
&lt;h2&gt;CORS for multiple domains&lt;/h2&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;\.(?:ttf|ttc|otf|eot|woff|woff2)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$http_origin&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;(https?://(.+\.)?(domain1|domain2|domain3)\.(?:me|co|com)&lt;/span&gt;$&lt;span class="s"&gt;)&lt;/span&gt; &lt;span class="s"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Access-Control-Allow-Origin&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$http_origin&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/a/27879729/3900519"&gt;https://stackoverflow.com/a/27879729/3900519&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="nginx"></category></entry><entry><title>Integrate Rollbar with Aurelia</title><link href="//www.jujens.eu/posts/en/2017/Aug/19/rollbar-aurelia/" rel="alternate"></link><published>2017-08-19T00:00:00+02:00</published><updated>2017-08-19T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-19:/posts/en/2017/Aug/19/rollbar-aurelia/</id><summary type="html">&lt;p&gt;I recently integrated &lt;a class="reference external" href="https://rollbar.com/"&gt;Rollbar&lt;/a&gt; (a service to &lt;cite&gt;Detect, diagnose and debug errors with ease&lt;/cite&gt;) into an Aurelia application. I explain here how I did it. I start by explaining how logging works with Aurelia and then how I integrated Rollbar into this.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#logging-with-aurelia" id="id1"&gt;Logging with Aurelia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#integration-with-rollbar" id="id2"&gt;Integration with Rollbar&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#using-rollbar-within-aurelia" id="id3"&gt;Using …&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;I recently integrated &lt;a class="reference external" href="https://rollbar.com/"&gt;Rollbar&lt;/a&gt; (a service to &lt;cite&gt;Detect, diagnose and debug errors with ease&lt;/cite&gt;) into an Aurelia application. I explain here how I did it. I start by explaining how logging works with Aurelia and then how I integrated Rollbar into this.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#logging-with-aurelia" id="id1"&gt;Logging with Aurelia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#integration-with-rollbar" id="id2"&gt;Integration with Rollbar&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#using-rollbar-within-aurelia" id="id3"&gt;Using Rollbar within Aurelia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#loading-rollbar" id="id4"&gt;Loading Rollbar&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="logging-with-aurelia"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Logging with Aurelia&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The main module to log things with Aurelia is simply named &lt;a class="reference external" href="https://github.com/aurelia/logging"&gt;aurelia-logging&lt;/a&gt;. It is responsible for:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Setting the log level you want with &lt;tt class="docutils literal"&gt;setLevel&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Create/get loggers with &lt;tt class="docutils literal"&gt;getLogger&lt;/tt&gt;. When you get a logger with this function, logs messages will be dispatched to all registered log appenders (more on that in a minute) while respecting the level of log you set.&lt;/li&gt;
&lt;li&gt;Defining the &lt;tt class="docutils literal"&gt;Appender&lt;/tt&gt; interface.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-logging&lt;/span&gt;&lt;/tt&gt; is a generic module to deal with logging but doesn't log anything by itself. It is defined this way so it can work in various environment (eg the browser and Node) and send logs where you want (let it be the browser console or Rollbar).&lt;/p&gt;
&lt;p&gt;To actually do some logging, we need to add at least one Appender with &lt;tt class="docutils literal"&gt;addAppender&lt;/tt&gt;. For instance, you can use the &lt;a class="reference external" href="https://github.com/aurelia/logging-console"&gt;aurelia-logging-console&lt;/a&gt; module to append log to the browser console. Or you can use &lt;a class="reference external" href="https://github.com/Jenselme/au-rollbar"&gt;au-rollbar&lt;/a&gt; to log the messages into Rollbar.&lt;/p&gt;
&lt;p&gt;Let's illustrate this with an example. Let's say I configure the log level to log only warnings and above with &lt;tt class="docutils literal"&gt;Logger.setLevel(Logger.logLevel.warn);&lt;/tt&gt; and that you added the &lt;tt class="docutils literal"&gt;ConsoleAppender&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;RollbarAppender&lt;/tt&gt; to the list of appenders with &lt;tt class="docutils literal"&gt;Logger.addAppender(new &lt;span class="pre"&gt;ConsoleAppender())&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Logger.addAppender(new &lt;span class="pre"&gt;RollbarAppender());&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;You then create your logger with &lt;tt class="docutils literal"&gt;let myLogger = &lt;span class="pre"&gt;Logger.getLogger('my-module')&lt;/span&gt;&lt;/tt&gt;. You then use the logger, eg:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;myLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A warning'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;myLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A debug message'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;A warning&lt;/tt&gt; message will be dispatched to the console and rollbar while &lt;tt class="docutils literal"&gt;A debug message&lt;/tt&gt; won't be logged anywhere.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="integration-with-rollbar"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Integration with Rollbar&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="using-rollbar-within-aurelia"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Using Rollbar within Aurelia&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In order to integrate Rollbar into Aurelia, I created a &lt;tt class="docutils literal"&gt;RollbarAppender&lt;/tt&gt; that implements the &lt;tt class="docutils literal"&gt;Appender&lt;/tt&gt; interface (see the interface definition &lt;a class="reference external" href="https://github.com/aurelia/logging/blob/master/src/index.js#L85"&gt;here&lt;/a&gt;). What it does is pretty straightforward: it dispatches incoming log messages to the proper methods of the &lt;tt class="docutils literal"&gt;Rollbar&lt;/tt&gt; object. Just like in &lt;tt class="docutils literal"&gt;ConsoleAppender&lt;/tt&gt; I prepend the level and id of the logger to the message.&lt;/p&gt;
&lt;p&gt;Since according to &lt;a class="reference external" href="https://rollbar.com/docs/notifier/rollbar.js/#usage"&gt;the doc&lt;/a&gt; I can only give one message, I put the eventual extra parameters of the function in a JSON object to log them as extra arguments.&lt;/p&gt;
&lt;p&gt;Here is the full code. You can download it &lt;a class="reference external" href="//www.jujens.eu/static/aurelia-rollbar/rollbar.js"&gt;here&lt;/a&gt;. You can also install it with &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;au-rollbar&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;RollbarAppender&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;    &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mainArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRollbar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`DEBUG [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;]: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mainArgs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_formatRest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;    &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mainArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRollbar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`INFO [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;]  &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mainArgs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_formatRest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;    &lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mainArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRollbar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`WARN [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;] &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mainArgs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_formatRest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;    &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mainArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getRollbar&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`ERROR [&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;]  &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;mainArgs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_formatRest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;    &lt;span class="nx"&gt;_formatRest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stingify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;extra&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;    &lt;span class="nx"&gt;getRollbar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rollbar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;// eslint-disable-line no-console
&lt;/span&gt;&lt;span class="ln"&gt;33 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Rollbar is not defined'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// eslint-disable-line no-console
&lt;/span&gt;&lt;span class="ln"&gt;34 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;            &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;                &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;                &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;                &lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;                &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;            &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rollbar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;45 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;46 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You then need to import it with something like &lt;tt class="docutils literal"&gt;import RollbarAppender from &lt;span class="pre"&gt;'./logging';&lt;/span&gt;&lt;/tt&gt; (or &lt;tt class="docutils literal"&gt;import RollbarAppender from &lt;span class="pre"&gt;'au-rollbar'&lt;/span&gt;&lt;/tt&gt; if you installed it with npm). You then need to configure your logging. Since I doubt you will want to enable it in development, I suggest you configure Aurelia like this (in your &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; file):&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RollbarAppender&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'au-rollbar'&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Logger&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-logging'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;    &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;standardConfiguration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;        &lt;span class="c1"&gt;// Only log to the console when developing (default configuration of developmentLogging)
&lt;/span&gt;&lt;span class="ln"&gt; 9 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;        &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developmentLogging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;        &lt;span class="c1"&gt;// Production logging is inspired by developmentLogging
&lt;/span&gt;&lt;span class="ln"&gt;12 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;        &lt;span class="c1"&gt;// This loads the ``aurelia-logging-console`` module and then configures logging.
&lt;/span&gt;&lt;span class="ln"&gt;13 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;        &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preTask&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;                    &lt;span class="s1"&gt;'aurelia-logging-console'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;                    &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bootstrapperName&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;            &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;                    &lt;span class="c1"&gt;// Once the module is loaded, we configure logging.
&lt;/span&gt;&lt;span class="ln"&gt;20 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="c1"&gt;// We add the ConsoleAppender so all messages are logged in the console of the browser.
&lt;/span&gt;&lt;span class="ln"&gt;21 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addAppender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ConsoleAppender&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;                    &lt;span class="c1"&gt;// If the Rollbar exists in the window object (ie if Rollbar is loaded),
&lt;/span&gt;&lt;span class="ln"&gt;23 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="c1"&gt;// we add the RollbarAppender so messages are sent to rollbar.
&lt;/span&gt;&lt;span class="ln"&gt;24 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="c1"&gt;// If it is not, we print a warning in the browser console.
&lt;/span&gt;&lt;span class="ln"&gt;25 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rollbar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;                        &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addAppender&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RollbarAppender&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;                    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;                        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Rollbar is not defined'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// eslint-disable-line no-console
&lt;/span&gt;&lt;span class="ln"&gt;29 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;                    &lt;span class="c1"&gt;// Configure logger to log only messages of level warning or above.
&lt;/span&gt;&lt;span class="ln"&gt;31 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;                    &lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;                &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;            &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;        &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;        &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-testing'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;    &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="loading-rollbar"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Loading Rollbar&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now we need to load the Rollbar script for Rollbar to actually work. Since in addition to logging messages with the &lt;tt class="docutils literal"&gt;Rollbar&lt;/tt&gt; object, Rollbar can log uncaught exception, it is better to load it as early as possible (to detect errors when Aurelia is bootstraping for instance). To achieve this, I decided to put the configuration and quickstart script (from &lt;a class="reference external" href="https://rollbar.com/docs/notifier/rollbar.js/"&gt;here&lt;/a&gt;) into a &lt;tt class="docutils literal"&gt;rollbar.js&lt;/tt&gt; script located in the &lt;tt class="docutils literal"&gt;scripts&lt;/tt&gt; folder. Then, since I use the CLI to build my project, I edited &lt;tt class="docutils literal"&gt;aurelia_project/aurelia.json&lt;/tt&gt; to add &lt;tt class="docutils literal"&gt;&amp;quot;scripts/rollbar.js&amp;quot;,&lt;/tt&gt; in the prepend section of the vendor bundle. So the definition of the vendor bundle looks like:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;    &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;vendor-bundle.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;    &lt;span class="nt"&gt;&amp;quot;prepend&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;node_modules/bluebird/js/browser/bluebird.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;scripts/polyfills.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;scripts/rollbar.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;node_modules/requirejs/require.js&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="nt"&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-binding&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-bootstrapper&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-dependency-injection&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-event-aggregator&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-framework&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-history&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-history-browser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-loader&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-loader-default&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-logging&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-logging-console&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-metadata&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-pal&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-pal-browser&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-path&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-polyfills&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-route-recognizer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-router&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-task-queue&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-templating&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;aurelia-templating-binding&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-templating-resources&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;../node_modules/aurelia-templating-resources/dist/amd&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-templating-resources&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;        &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-templating-router&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;../node_modules/aurelia-templating-router/dist/amd&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-templating-router&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;        &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;        &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-testing&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;../node_modules/aurelia-testing/dist/amd&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;45 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-testing&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;46 &lt;/span&gt;            &lt;span class="nt"&gt;&amp;quot;env&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;dev&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt;49 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you want to load Rollbar from another location, you can use the &lt;tt class="docutils literal"&gt;rollbarJsUrl&lt;/tt&gt; property in the configuration object and give it the URL from which you want to load the script.&lt;/p&gt;
&lt;p&gt;That's it. If you have any question or remark, please leave a comment.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="rollbar"></category></entry><entry><title>A sample application with Aurelia UX</title><link href="//www.jujens.eu/posts/en/2017/Aug/14/aurelia-ux/" rel="alternate"></link><published>2017-08-14T00:00:00+02:00</published><updated>2017-08-14T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-14:/posts/en/2017/Aug/14/aurelia-ux/</id><summary type="html">&lt;p&gt;This is a follow up to my &lt;a class="reference external" href="//www.jujens.eu/posts/en/2016/Mar/15/ionic2-aurelia-f7/"&gt;Small comparison of ionic2 and Aurelia + Framework7 for hybrid mobile applications&lt;/a&gt; article where I compared ionic2 and Aurelia with Framework 7 for building an hybrid applications. At the time, Aurelia UX was not yet ready (and we were expecting a different, closed source …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is a follow up to my &lt;a class="reference external" href="//www.jujens.eu/posts/en/2016/Mar/15/ionic2-aurelia-f7/"&gt;Small comparison of ionic2 and Aurelia + Framework7 for hybrid mobile applications&lt;/a&gt; article where I compared ionic2 and Aurelia with Framework 7 for building an hybrid applications. At the time, Aurelia UX was not yet ready (and we were expecting a different, closed source project called Aurelia Interface). Now, Aurelia UX made huge process and I was able to write the sample application in it. I describe here how it went. The code is available &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/tree/master/aurelia-ux-todo"&gt;on github&lt;/a&gt; with the other applications.&lt;/p&gt;
&lt;p&gt;As a reminder, here are the features of the TODO application:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;List all the saved todos (home page)&lt;/li&gt;
&lt;li&gt;Edit an existing todo&lt;/li&gt;
&lt;li&gt;Add a todo&lt;/li&gt;
&lt;li&gt;Mark a todo as done on the home page. Done todos must have their title strike-through on the home page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wrote the application in TypeScript and CSS, since they are the languages Aurelia UX and its showcase application are written in. Here are screenshots of the result:&lt;/p&gt;
&lt;img alt="Page to list all TODOs" class="align-center" src="/images/aurelia-ux/todo-list.png" style="width: 25%;" /&gt;
&lt;img alt="Page to add or edit todo" class="align-center" src="/images/aurelia-ux/add-todo.png" style="width: 25%;" /&gt;
&lt;img alt="The menu of the application" class="align-center" src="/images/aurelia-ux/menu.png" style="width: 25%;" /&gt;
&lt;p&gt;I based my application on the &lt;a class="reference external" href="https://github.com/aurelia/app-ux-showcase"&gt;Aurelia UX showcase app&lt;/a&gt;: I cloned this repo, remove the code I didn't need and started to add my code. It is structured like this:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;An &lt;tt class="docutils literal"&gt;assets&lt;/tt&gt; folder with the images and fonts&lt;/li&gt;
&lt;li&gt;An &lt;tt class="docutils literal"&gt;aurelia_project&lt;/tt&gt; folder that contains the configuration for the &lt;a class="reference external" href="https://github.com/aurelia/cli"&gt;cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;custom_typings&lt;/tt&gt; folder for TypeScript type definitions&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;scripts&lt;/tt&gt; folder created by the cli for some useful scripts (eg &lt;tt class="docutils literal"&gt;require.js&lt;/tt&gt;)&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; folder that contains the application in itself. It contains:&lt;ul&gt;
&lt;li&gt;The &lt;tt class="docutils literal"&gt;main.ts&lt;/tt&gt; file which is the entry point to the application&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;routes.ts&lt;/tt&gt; to configure the routes of the application&lt;/li&gt;
&lt;li&gt;CSS files common to all the application&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;app.ts&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;app.css&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;app.html&lt;/tt&gt; which configure the layout of the page and configures the menu and the router&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;models&lt;/tt&gt; folder that contains type definition of the application for TypeScript&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;pages&lt;/tt&gt; folder which contains the HTML, JS and CSS code for each routes&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;services&lt;/tt&gt; folder that contains services for the application&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that's done, let's take a look at the code. I won't detail the &lt;tt class="docutils literal"&gt;main.ts&lt;/tt&gt; too much since it is very classic. I'll just point out to &lt;a class="reference external" href="https://github.com/aurelia/app-ux-showcase/blob/master/src/main.ts#L18"&gt;line 18&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-ux'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This is where we enable Aurelia UX in our application. If we don't, we won't be able to use its tags and attributes in our application.&lt;/p&gt;
&lt;p&gt;In the &lt;tt class="docutils literal"&gt;app.ts&lt;/tt&gt;, we import &lt;tt class="docutils literal"&gt;AureliaUX&lt;/tt&gt; from the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-ux&lt;/span&gt;&lt;/tt&gt; module and inject it into our application. If you look at the constructor, you'll see the first interesting piece:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;ux&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AureliaUX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;design&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MAIN_THEME&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;ux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;design&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MAIN_THEME&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showNavigationMenu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here is the definition of &lt;tt class="docutils literal"&gt;MAIN_THEME&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAIN_THEME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;primary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'#009688'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;accent&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'#4CAF50'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We are using this to set the color of the style of our application. If you look at the corresponding CSS, you can see something like:&lt;/p&gt;
&lt;pre class="code CSS literal-block"&gt;
&lt;span class="nt"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;${$&lt;/span&gt;&lt;span class="n"&gt;design&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;$design.primaryForeground&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;As you may guess, thanks to the &lt;tt class="docutils literal"&gt;design&lt;/tt&gt; property of the &lt;tt class="docutils literal"&gt;AureliaUX&lt;/tt&gt; object, our CSS code and our TypeScript code are linked. The content of &lt;tt class="docutils literal"&gt;ux.design.primary&lt;/tt&gt; will replace all the occurrences of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${$design.primary}&lt;/span&gt;&lt;/tt&gt; in the CSS. And the best part is: it is dynamic! If you change &lt;tt class="docutils literal"&gt;ux.design.primary&lt;/tt&gt; in your application, the style will update to reflect it. You can test this by opening the hamburger menu and clicking on the &lt;em&gt;Alternate theme&lt;/em&gt; check box. This will call the &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/master/aurelia-ux-todo/src/app.ts#L37"&gt;theme changed&lt;/a&gt; function to update the style of the application.&lt;/p&gt;
&lt;p&gt;To use this feature in our HTML, we must:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Require the CSS file with the &lt;tt class="docutils literal"&gt;ux&lt;/tt&gt; hash:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;require&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./app.css#ux&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;require&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Use &lt;tt class="docutils literal"&gt;styles.header&lt;/tt&gt; as a custom attribute, like this:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="na"&gt;styles&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;styles&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header-h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;${router.currentInstruction.config.navModel.title}&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;styles&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clickable&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;_self&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;toggleNavigationMenu()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;styles&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header-burger&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fa fa-bars&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Simple and efficient, isn't?&lt;/p&gt;
&lt;p&gt;Navigation in the application is handled by Aurelia's router. Since you are probably already familiar with it, I won't detail that here.&lt;/p&gt;
&lt;p&gt;Lets take a look at the edit page. There isn't much in the TS code: we basically setup the validation (to know more about validation, see &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Jan/24/aurelia-validation/"&gt;this article&lt;/a&gt;), rely on the storage service to load the TODO to edit (if we are editing an existing TODO) and save it in the cache. We also use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;this.router.navigateToRoute('list');&lt;/span&gt;&lt;/tt&gt; to navigate in the application.&lt;/p&gt;
&lt;p&gt;The more interesting part is the HTML where I use tags defined by Aurelia UX. The form to add a TODO is located in a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ux-form&lt;/span&gt;&lt;/tt&gt; tag. I then use the custom tags to create:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;The input for the title:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ux-input&lt;/span&gt;
             &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt;
             &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;todo.title &amp;amp; validate&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ux-input&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The textarea:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ux-textarea&lt;/span&gt;
              &lt;span class="na"&gt;auto-resize&lt;/span&gt;
              &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Description&amp;quot;&lt;/span&gt;
              &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;todo.description &amp;amp; validate&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ux-textarea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The done checkbox:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ux-field&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ux-checkbox&lt;/span&gt; &lt;span class="na"&gt;checked&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;todo.done&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Done&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ux-checkbox&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ux-field&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The save button:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ux-button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;raised&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;save()&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!canSave&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ux-button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, they are simply custom elements and behave like any other custom elements would.&lt;/p&gt;
&lt;p&gt;The list page is quite basic so I won't detail it. If you have questions, please leave a comment.&lt;/p&gt;
&lt;p&gt;What I didn't test:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Building the application and sending it to my phone. I suspect this will be similar to what you can do with Framework 7 or ionic.&lt;/li&gt;
&lt;li&gt;Using SCSS instead of CSS. I frankly have no idea how this would behave in conjuction with how you can interact with CSS inside Aurelia UX (things like &lt;tt class="docutils literal"&gt;ux.design.primary = MAIN_THEME.primary;&lt;/tt&gt; in your JS and &lt;tt class="docutils literal"&gt;background: &lt;span class="pre"&gt;${$design.primary};&lt;/span&gt;&lt;/tt&gt; in the CSS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is currently no documentation about Aurelia UX but the &lt;a class="reference external" href="https://github.com/aurelia/app-ux-showcase"&gt;showcase app&lt;/a&gt; contains example for all the available components. You can clone the repo and launch it with &lt;tt class="docutils literal"&gt;npm install&lt;/tt&gt; to install the dependencies and then &lt;tt class="docutils literal"&gt;au run&lt;/tt&gt; to run it.&lt;/p&gt;
&lt;p&gt;To conclude: I find the project promising. It's easy to work with, has some really nice features (such as the ability to have easy links between the code and the CSS). The look and feel of the application is great. The integration with Aurelia is perfect. It also looks a lot like &lt;a class="reference external" href="http://ionicframework.com/"&gt;ionic&lt;/a&gt; so developers used to this framework shouldn't be lost. They are however some downsides: this is still a work in progress and some components don't exist yet (eg &lt;a class="reference external" href="https://github.com/aurelia/ux/issues/19"&gt;select&lt;/a&gt;). I also found that the checkboxes are not always reliable. Some clicks where not taken into accounts. I don't know if this came from my browser (FireFox for desktop, I haven't tested on mobile) or from the way the check boxes are rendered (they are not real check boxes but divs so they can be styled correctly).&lt;/p&gt;
&lt;p&gt;That's it for today. If you have a question or remark, please leave a comment below.&lt;/p&gt;
</content><category term="Aurelia"></category><category term="ionic2"></category><category term="angular2"></category><category term="aurelia"></category><category term="framework7"></category><category term="android"></category><category term="mobile"></category></entry><entry><title>Chiffrer des fichiers avec GPG</title><link href="//www.jujens.eu/posts/2017/Aug/08/gpg-crypt/" rel="alternate"></link><published>2017-08-08T00:00:00+02:00</published><updated>2017-08-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-08:/posts/2017/Aug/08/gpg-crypt/</id><summary type="html">&lt;p&gt;Voici deux fonctions bash qui permettent de chiffrer et déchiffrer un fichier ou un dossier avec &lt;a class="reference external" href="https://gnupg.org/"&gt;GPG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Les dossiers sont compressés dans une archive ZIP avant le chiffrement.&lt;/p&gt;
&lt;p&gt;Le chiffrement laisse les fichiers d'origine intacts. Le déchiffrement laisse le fichier chiffré intact.&lt;/p&gt;
&lt;p&gt;Ces fonctions auront leur place dans votre &lt;tt class="docutils literal"&gt;.bashrc …&lt;/tt&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Voici deux fonctions bash qui permettent de chiffrer et déchiffrer un fichier ou un dossier avec &lt;a class="reference external" href="https://gnupg.org/"&gt;GPG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Les dossiers sont compressés dans une archive ZIP avant le chiffrement.&lt;/p&gt;
&lt;p&gt;Le chiffrement laisse les fichiers d'origine intacts. Le déchiffrement laisse le fichier chiffré intact.&lt;/p&gt;
&lt;p&gt;Ces fonctions auront leur place dans votre &lt;tt class="docutils literal"&gt;.bashrc&lt;/tt&gt; ou équivalent.&lt;/p&gt;
&lt;p&gt;Pour chiffrer : &lt;tt class="docutils literal"&gt;gpgcrypt FICHIER&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Pour déchiffrer : &lt;tt class="docutils literal"&gt;gpgdecrypt FICHIER&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
gpgcrypt&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You must supply an argument&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        zip -r &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.zip&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        gpg --output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.zip.gpg&amp;quot;&lt;/span&gt; --symmetric &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.zip&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        gpg --output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.gpg&amp;quot;&lt;/span&gt; --symmetric &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

gpgdecrypt&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You must supply an argument&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        gpg --output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; --decrypt &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;file --mime-type --brief &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'application/zip'&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            unzip &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;fi&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="GPG"></category><category term="securité"></category></entry><entry><title>Chiffrer des fichiers avec GPG</title><link href="//www.jujens.eu/posts/en/2017/Aug/08/gpg-crypt/" rel="alternate"></link><published>2017-08-08T00:00:00+02:00</published><updated>2017-08-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-08:/posts/en/2017/Aug/08/gpg-crypt/</id><summary type="html">&lt;p&gt;Here are two bash functions to crypt/decrypt files with &lt;a class="reference external" href="https://gnupg.org/"&gt;GPG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Folder are compressed in a ZIP file before being encrypted.&lt;/p&gt;
&lt;p&gt;Crypting leaves original files untouched. So does decrypting.&lt;/p&gt;
&lt;p&gt;These functions have their place in your &lt;tt class="docutils literal"&gt;.bashrc&lt;/tt&gt; or equivalent.&lt;/p&gt;
&lt;p&gt;To crypt: &lt;tt class="docutils literal"&gt;gpgcrypt FICHIER&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;To decrypt: &lt;tt class="docutils literal"&gt;gpgdecrypt FICHIER&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
gpgcrypt&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z …&lt;/pre&gt;</summary><content type="html">&lt;p&gt;Here are two bash functions to crypt/decrypt files with &lt;a class="reference external" href="https://gnupg.org/"&gt;GPG&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Folder are compressed in a ZIP file before being encrypted.&lt;/p&gt;
&lt;p&gt;Crypting leaves original files untouched. So does decrypting.&lt;/p&gt;
&lt;p&gt;These functions have their place in your &lt;tt class="docutils literal"&gt;.bashrc&lt;/tt&gt; or equivalent.&lt;/p&gt;
&lt;p&gt;To crypt: &lt;tt class="docutils literal"&gt;gpgcrypt FICHIER&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;To decrypt: &lt;tt class="docutils literal"&gt;gpgdecrypt FICHIER&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
gpgcrypt&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You must supply an argument&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        zip -r &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.zip&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        gpg --output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.zip.gpg&amp;quot;&lt;/span&gt; --symmetric &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.zip&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        gpg --output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;.gpg&amp;quot;&lt;/span&gt; --symmetric &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

gpgdecrypt&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You must supply an argument&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        gpg --output &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; --decrypt &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;file --mime-type --brief &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'application/zip'&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
            unzip &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;%.*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
        &lt;span class="k"&gt;fi&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="GPG"></category><category term="securité"></category></entry><entry><title>Extraire le HTML d'un email au format mbox</title><link href="//www.jujens.eu/posts/2017/Aug/07/extract-html-mbox/" rel="alternate"></link><published>2017-08-07T00:00:00+02:00</published><updated>2017-08-07T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-07:/posts/2017/Aug/07/extract-html-mbox/</id><summary type="html">&lt;p&gt;Voici un petit script Python pour convertir un mail au format mbox en HTML. Pour que le script fonctionne, il faut soit que le corps du message soit du HTML (recommandé) soit que la première pièce jointe du message contienne le message en HTML.&lt;/p&gt;
&lt;p&gt;Par défaut, le script traitera tous …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Voici un petit script Python pour convertir un mail au format mbox en HTML. Pour que le script fonctionne, il faut soit que le corps du message soit du HTML (recommandé) soit que la première pièce jointe du message contienne le message en HTML.&lt;/p&gt;
&lt;p&gt;Par défaut, le script traitera tous les fichiers dont l'extension est mbox dans le dossier courant. Vous pouvez lui passer le chemin vers un dossier pour qu'il traite les fichiers de ce dossier. Le HTML est sauvegardé dans un fichier du même nom que l'original, dans le même dossier avec l'extension &lt;tt class="docutils literal"&gt;.html&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mailbox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mboxMessage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;os.path&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;splitext&lt;/span&gt;


&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'*.mbox'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mail_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mboxMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mail_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'charset=iso-8859-1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'charset=utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Vous pouvez aussi le trouver sur github : &lt;a class="reference external" href="https://github.com/Jenselme/dot-files-shell/blob/master/bin/extract-html-email.py"&gt;https://github.com/Jenselme/dot-files-shell/blob/master/bin/extract-html-email.py&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="mail"></category><category term="Python"></category></entry><entry><title>Extraire le HTML d'un email au format mbox</title><link href="//www.jujens.eu/posts/en/2017/Aug/07/extract-html-mbox/" rel="alternate"></link><published>2017-08-07T00:00:00+02:00</published><updated>2017-08-07T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-08-07:/posts/en/2017/Aug/07/extract-html-mbox/</id><summary type="html">&lt;p&gt;Here is a small script to convert mail in the mbox format to HTML. For the script to work, the body of the message (recommended) or its first attachment must contain the HTML code.&lt;/p&gt;
&lt;p&gt;By default, the script will convert all mbox files of the current folder. You can also …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Here is a small script to convert mail in the mbox format to HTML. For the script to work, the body of the message (recommended) or its first attachment must contain the HTML code.&lt;/p&gt;
&lt;p&gt;By default, the script will convert all mbox files of the current folder. You can also give it a path to another folder as first argument. The HTML is saved in the same folder than the original file in a file with the same name and the &lt;tt class="docutils literal"&gt;.html&lt;/tt&gt; extension.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mailbox&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mboxMessage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;os.path&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;splitext&lt;/span&gt;


&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'*.mbox'&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mail_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mboxMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mail_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'charset=iso-8859-1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'charset=utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can also find it on github: &lt;a class="reference external" href="https://github.com/Jenselme/dot-files-shell/blob/master/bin/extract-html-email.py"&gt;https://github.com/Jenselme/dot-files-shell/blob/master/bin/extract-html-email.py&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="mail"></category><category term="Python"></category></entry><entry><title>Use Linux user namespaces to fix permissions in docker volumes</title><link href="//www.jujens.eu/posts/en/2017/Jul/02/docker-userns-remap/" rel="alternate"></link><published>2017-07-02T00:00:00+02:00</published><updated>2017-07-02T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-07-02:/posts/en/2017/Jul/02/docker-userns-remap/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-docker" id="id1"&gt;Configure docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-the-subordinate-uid-gid" id="id2"&gt;Configure the subordinate uid/gid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#tests" id="id3"&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#bonus" id="id4"&gt;Bonus&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-files" id="id5"&gt;Create files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#unix-sockets" id="id6"&gt;Unix sockets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#external-links" id="id7"&gt;External links&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Not long ago, I publish &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Feb/15/docker-unix-socket/"&gt;an article&lt;/a&gt; about using Unix sockets with docker. These sockets where in docker volumes so they could be shared between various containers. The key idea was to change the …&lt;/p&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-docker" id="id1"&gt;Configure docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-the-subordinate-uid-gid" id="id2"&gt;Configure the subordinate uid/gid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#tests" id="id3"&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#bonus" id="id4"&gt;Bonus&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-files" id="id5"&gt;Create files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#unix-sockets" id="id6"&gt;Unix sockets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#external-links" id="id7"&gt;External links&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Not long ago, I publish &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Feb/15/docker-unix-socket/"&gt;an article&lt;/a&gt; about using Unix sockets with docker. These sockets where in docker volumes so they could be shared between various containers. The key idea was to change the UID and GID of the user that owns the socket in the container so they match those of the user that built the image. The main issue with this approach is that it requires you to build to container with the user that will run it. This makes the solution not portable.&lt;/p&gt;
&lt;p&gt;Hopefully, the Linux kernel allows us to use an alternative to map user id inside the container to a predictable user id outside: user id namespaces. According to &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Linux_namespaces"&gt;wikipedia&lt;/a&gt;: &lt;cite&gt;Namespaces are a feature of the Linux kernel that isolates and virtualizes system resources of a collection of processes. Examples of resources that can be virtualized include process IDs, hostnames, user IDs, network access, interprocess communication, and filesystems. Namespaces are a fundamental aspect of containers on Linux.&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;For instance, thanks to the PID namespace, a process run inside a container can &amp;quot;think&amp;quot; it has the PID 1 inside a container while in fact it has another one. The same is true with user namespace: a user can &amp;quot;think&amp;quot; it has the 0 uid (root) while it fact it has the 1000 user id (some standard user). This will allow us to be sure for the files in a docker volumes that:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;All files belonging to the root user in the container will belong to a user of the system that is not root in the host.&lt;/li&gt;
&lt;li&gt;All files belonging to other users in the container will be mapped to predictable uid (more on that latter).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="configure-docker"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Configure docker&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Lets configure docker to do all that.&lt;/p&gt;
&lt;p&gt;First we either need to start the docker daemon with the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--userns-remap&lt;/span&gt; USER&lt;/tt&gt; flag or make sure the configuration file of the docker daemon (&lt;tt class="docutils literal"&gt;/etc/docker/daemon.json&lt;/tt&gt;) contains something like:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;userns-remap&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;USER&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;In both cases, &lt;tt class="docutils literal"&gt;USER&lt;/tt&gt; must be a valid user of the system (ie present in &lt;tt class="docutils literal"&gt;/etc/passwd&lt;/tt&gt;).&lt;/li&gt;
&lt;li&gt;Don't forget to restart the daemon if you have to edit the file.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="configure-the-subordinate-uid-gid"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Configure the subordinate uid/gid&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="http://man7.org/linux/man-pages/man5/subuid.5.html"&gt;subuid&lt;/a&gt; and &lt;a class="reference external" href="http://man7.org/linux/man-pages/man5/subgid.5.html"&gt;subgid&lt;/a&gt; are used to specify the user/group ids an ordinary user can use to configure id mapping in a user namespace. They are written like: &lt;tt class="docutils literal"&gt;username:id:count&lt;/tt&gt;. For instance, with &lt;tt class="docutils literal"&gt;jenselme:100000:65536&lt;/tt&gt; it means that user &lt;tt class="docutils literal"&gt;jenselme&lt;/tt&gt; can use 65536 user ids starting at 100000.&lt;/p&gt;
&lt;p&gt;This will be used by docker to properly remap uid in the container to the host. For instance, with &lt;tt class="docutils literal"&gt;jenselme:100000:65536&lt;/tt&gt;, a file with a uid of 33 in the container, will be a file with a uid of 100032 in the host. And you will have access to that file. Neat, isn't it?&lt;/p&gt;
&lt;p&gt;Now that we've seen the theory, let's configure them properly. First, edit &lt;tt class="docutils literal"&gt;/etc/subuid&lt;/tt&gt; and add (replace &lt;tt class="docutils literal"&gt;jenselme&lt;/tt&gt; by your own user name):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
jenselme:1000:1
jenselme:100000:65536
&lt;/pre&gt;
&lt;p&gt;You should be able to understand the second line. The first one is there for a slightly different purpose: make sure that all files created by root belong to the user with uid 1000. That's me on my machine, you should of course use your uid (you can get it with &lt;tt class="docutils literal"&gt;id &lt;span class="pre"&gt;-u&lt;/span&gt; USER&lt;/tt&gt;). Otherwise, they will belong to uid 100000.&lt;/p&gt;
&lt;p&gt;Now, edit &lt;tt class="docutils literal"&gt;/etc/subgid&lt;/tt&gt; and add (replace &lt;tt class="docutils literal"&gt;jenselme&lt;/tt&gt; by your own user name):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
jenselme:982:1
jenselme:100000:65536
&lt;/pre&gt;
&lt;p&gt;The second line is the name in both cases. I didn't use &lt;tt class="docutils literal"&gt;jenselme:1000:1&lt;/tt&gt; but &lt;tt class="docutils literal"&gt;jenselme:982:1&lt;/tt&gt;. On my machine, 982 is the gui of the docker group (you can get it with &lt;tt class="docutils literal"&gt;getent group docker&lt;/tt&gt;). This means that all files created by root, will belong to me and to the docker group. This &amp;quot;trick&amp;quot; can be handy if for some reason you need to share files with the docker daemon. For instance, software like &lt;a class="reference external" href="https://traefik.io/"&gt;traefic&lt;/a&gt; may need to read/write to the docker socket. By default, for this socket we have:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[root&amp;#64;fastolfe ~]# ll /var/run/docker.sock
srw-rw----. 1 root docker 0 Jun 11 18:18 /var/run/docker.sock
&lt;/pre&gt;
&lt;p&gt;This means that if in the outside the container the uid of root and its guid are mapped to those of jenselme, traefic won't be able to communicate with the socket because of the permissions of the file. Map the gid of root in the container to the gid of docker in the host allows us to prevent that issue.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note on security:&lt;/strong&gt; Giving access to the docker socket is a problem from a security standpoint since it allows a container to create new containers thus giving it access to the whole host system &lt;em&gt;with root permissions&lt;/em&gt;, eg by running &lt;tt class="docutils literal"&gt;docker run &lt;span class="pre"&gt;-it&lt;/span&gt; &lt;span class="pre"&gt;-v&lt;/span&gt; &lt;span class="pre"&gt;--privileged&lt;/span&gt; &lt;span class="pre"&gt;-v&lt;/span&gt; &lt;span class="pre"&gt;/:/host&lt;/span&gt; &lt;span class="pre"&gt;--userns=host&lt;/span&gt; fedora chroot /host&lt;/tt&gt;. That is why SELinux will prevent the docker socket to be mounted in a volume by default. You should be aware of that when you do this. See &lt;a class="reference external" href="http://danwalsh.livejournal.com/74095.html"&gt;this&lt;/a&gt; for more on that topic.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tests"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Tests&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we are all set, let's start the docker daemon (or restart it).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note to SELinux users:&lt;/strong&gt; You need to append &lt;tt class="docutils literal"&gt;Z&lt;/tt&gt; (capital z) when mounting the volumes, like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-v&lt;/span&gt; &lt;span class="pre"&gt;$(pwd)/test:/test/:Z&lt;/span&gt;&lt;/tt&gt;. Otherwise, the SELinux context will not be correct and you won't be able to access the volumes from the container. See &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/May/24/docker/#volumes"&gt;this docker tip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The first thing you should notice is that if you had downloaded images or created containers, you will not see them with &lt;tt class="docutils literal"&gt;docker images&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;docker ps &lt;span class="pre"&gt;-a&lt;/span&gt;&lt;/tt&gt;. That's because, when user re-mapping is enabled, all images and containers are located in a dedicated subfolder. On my machine, that is &lt;tt class="docutils literal"&gt;/var/lib/docker/1000.982&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Now that we know this is expected, let's try things. Run somewhere:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
docker run -it -v &amp;quot;$(pwd)/test:/test/&amp;quot; nginx /bin/bash
&lt;/pre&gt;
&lt;p&gt;This will open a bash prompt as root in the container. Go to the volume with &lt;tt class="docutils literal"&gt;cd /test&lt;/tt&gt; and create a file: &lt;tt class="docutils literal"&gt;touch rootfile&lt;/tt&gt;. If you run a &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/tt&gt; inside the container, you should see something like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
root&amp;#64;02a5bcc1757c:/test# ls -l
total 0
-rw-r--r--. 1 root   root 0 Jun 11 16:25 rootfile
&lt;/pre&gt;
&lt;p&gt;Let's check the uid and gid to be sure:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
root&amp;#64;02a5bcc1757c:/test# ls -ln
total 0
-rw-r--r--. 1 0 0 0 Jun 11 16:25 rootfile
&lt;/pre&gt;
&lt;p&gt;So the file belongs to root and its uid is 0 as well as its gid.&lt;/p&gt;
&lt;p&gt;Now run &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/tt&gt; in the host:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
▶ ls -l
total 0
-rw-r--r--. 1 jenselme docker 0 Jun 11 18:25 rootfile
&lt;/pre&gt;
&lt;p&gt;Let's check the uid and guid:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
▶ ls -ln
total 0
-rw-r--r--. 1   1000 982 0 Jun 11 18:25 rootfile
&lt;/pre&gt;
&lt;p&gt;That's correct. Now let's do the same thing wit the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt; user. First, let's give some permissions on the &lt;tt class="docutils literal"&gt;/test&lt;/tt&gt; folder to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt; user. Since this is just a test, let's run &lt;tt class="docutils literal"&gt;chmod 777 /test&lt;/tt&gt;. Now, switch to this user with &lt;tt class="docutils literal"&gt;su &lt;span class="pre"&gt;-s&lt;/span&gt; /bin/bash &lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt;. You should now be in the &lt;tt class="docutils literal"&gt;/test&lt;/tt&gt; directory connected as &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt;. Create a file with &lt;tt class="docutils literal"&gt;touch &lt;span class="pre"&gt;www-data-file&lt;/span&gt;&lt;/tt&gt;. You should see something like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
www-data&amp;#64;02a5bcc1757c:/test$ ls -l
total 0
-rw-r--r--. 1 root     root     0 Jun 11 16:36 rootfile
-rw-r--r--. 1 www-data www-data 0 Jun 11 16:38 www-data-file
&lt;/pre&gt;
&lt;p&gt;And:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
www-data&amp;#64;02a5bcc1757c:/test$ ls -ln
total 0
-rw-r--r--. 1  0  0 0 Jun 11 16:36 rootfile
-rw-r--r--. 1 33 33 0 Jun 11 16:38 www-data-file
&lt;/pre&gt;
&lt;p&gt;As far as the host is concerned, we have:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
▶ ls -l
total 0
-rw-r--r--. 1 jenselme docker 0 Jun 11 18:36 rootfile
-rw-r--r--. 1   100032 100032 0 Jun 11 18:38 www-data-file
&lt;/pre&gt;
&lt;p&gt;And&lt;/p&gt;
&lt;pre class="literal-block"&gt;
▶ ls -ln
total 0
-rw-r--r--. 1   1000    982 0 Jun 11 18:36 rootfile
-rw-r--r--. 1 100032 100032 0 Jun 11 18:38 www-data-file
&lt;/pre&gt;
&lt;p&gt;Now let's create some files from the host. For instance, let's do &lt;tt class="docutils literal"&gt;touch &lt;span class="pre"&gt;www-data-file-from-host&lt;/span&gt;&lt;/tt&gt;. In the host it currently belongs to the current user. Let's see in the container:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
www-data&amp;#64;02a5bcc1757c:/test$ ls -l
total 0
-rw-r--r--. 1 root     root     0 Jun 11 16:36 rootfile
-rw-r--r--. 1 www-data www-data 0 Jun 11 16:38 www-data-file
-rw-r--r--. 1 root     nogroup  0 Jun 11 16:41 www-data-file-from-host
&lt;/pre&gt;
&lt;p&gt;It belongs to &lt;tt class="docutils literal"&gt;root&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;nogroup&lt;/tt&gt; as expected (in the host, the file belongs to &lt;tt class="docutils literal"&gt;jenselme:jenselme&lt;/tt&gt; not &lt;tt class="docutils literal"&gt;jenselme:docker&lt;/tt&gt;, hence the &lt;tt class="docutils literal"&gt;nogroup&lt;/tt&gt;, I could run &lt;tt class="docutils literal"&gt;chown jenselme:docker &lt;span class="pre"&gt;www-data-file-from-host&lt;/span&gt;&lt;/tt&gt; to fix the gid). If you check the uid and gid, you will see it is also as expected.&lt;/p&gt;
&lt;p&gt;Now let's change the owner of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data-file-from-host&lt;/span&gt;&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;100032:100032&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;chown 100032:100032 &lt;span class="pre"&gt;www-data-file-from-host&lt;/span&gt;&lt;/tt&gt; (this must be run as root to prevent an &lt;em&gt;Operation not permitted&lt;/em&gt;). I let you check the owner, uid, gid in the container. You can also check that the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt; user can write in the file with &lt;tt class="docutils literal"&gt;echo 'test' &amp;gt; &lt;span class="pre"&gt;www-data-file-from-host&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;This looks good isn't it? I found however one dark spot in this. If you try to edit &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data-file-from-host&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data-file&lt;/span&gt;&lt;/tt&gt; in the host, it will fail with &lt;em&gt;permission denied&lt;/em&gt;. As far as I understand the subuid and subgid, this is not normal. If someone has an explanation for this, please leave a comment. I see two workarounds for that:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;The basic:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Create a group with id &lt;tt class="docutils literal"&gt;100032&lt;/tt&gt; (as root): &lt;tt class="docutils literal"&gt;groupadd &lt;span class="pre"&gt;-g&lt;/span&gt; 100032 &lt;span class="pre"&gt;docker-www-data&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Add yourself to this group (as root): &lt;tt class="docutils literal"&gt;usermod &lt;span class="pre"&gt;-aG&lt;/span&gt; &lt;span class="pre"&gt;docker-www-data&lt;/span&gt; jenselme&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Disconnect/reconnect or use the &lt;tt class="docutils literal"&gt;newgrp &lt;span class="pre"&gt;docker-www-data&lt;/span&gt;&lt;/tt&gt; command to take this change into account.&lt;/li&gt;
&lt;li&gt;Give write permission to the group in the container: &lt;tt class="docutils literal"&gt;chmod g=rw &lt;span class="pre"&gt;www-data-file&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Write in the file.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You cannot do anything about the user since you can only have one user id.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;The elegant: use ACL (Access Control List). See the &lt;a class="reference internal" href="#external-links"&gt;external links&lt;/a&gt; section to learn more about ACL. TL;DR, ACLs are a way to extend the standard permissions of the filesystem. With them, you can set permissions for a file or directory with very thin granularity for each users and groups of the system. To enable ACLs, run as root:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;setfacl &lt;span class="pre"&gt;-Rdm&lt;/span&gt; u:USER:rwX DIR&lt;/tt&gt; (replace &lt;tt class="docutils literal"&gt;USER&lt;/tt&gt; by a username and &lt;tt class="docutils literal"&gt;DIR&lt;/tt&gt; by a path to a directory or file). This will:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-R&lt;/span&gt;&lt;/tt&gt; recurse on subfolders.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-d&lt;/span&gt;&lt;/tt&gt; default to this rule. This means that the ACL will apply to all files and directories created in &lt;tt class="docutils literal"&gt;DIR&lt;/tt&gt; after the &lt;tt class="docutils literal"&gt;setfacl&lt;/tt&gt; was run.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-m&lt;/span&gt;&lt;/tt&gt; modify the rule to &lt;tt class="docutils literal"&gt;u:USER:rwX&lt;/tt&gt; that is give to the user (&lt;tt class="docutils literal"&gt;u:&lt;/tt&gt;) &lt;tt class="docutils literal"&gt;USER&lt;/tt&gt; the permissions &lt;tt class="docutils literal"&gt;rwX&lt;/tt&gt;. The capital &lt;tt class="docutils literal"&gt;X&lt;/tt&gt; means &lt;em&gt;give execution permission to all folders and to files that have the execute permissions&lt;/em&gt;. This prevent us to make all files executable.&lt;/li&gt;
&lt;li&gt;apply to &lt;tt class="docutils literal"&gt;DIR&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;setfacl &lt;span class="pre"&gt;-Rm&lt;/span&gt; u:USER:rwX DIR&lt;/tt&gt; (replace &lt;tt class="docutils literal"&gt;USER&lt;/tt&gt; by a username and &lt;tt class="docutils literal"&gt;DIR&lt;/tt&gt; by a path to a directory or file). This will apply the ACL rule on the existing files in &lt;tt class="docutils literal"&gt;DIR&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="bonus"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Bonus&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="create-files"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Create files&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you can't or don't want to create the files (eg logs) when the images is created or when you start the container and be sure the container will be able to create them without running &lt;tt class="docutils literal"&gt;chmod &lt;span class="pre"&gt;-R&lt;/span&gt; 777 DIR&lt;/tt&gt;, you can use the commands below. We assume in this example that in a &lt;tt class="docutils literal"&gt;log&lt;/tt&gt; folder, we will have many volumes. Each volume will contain the logs of a container.&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Create all the containers with the proper volumes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Run &lt;tt class="docutils literal"&gt;chmod u=rwX,g=rwX,o=rwX &lt;span class="pre"&gt;-R&lt;/span&gt; log/&lt;/tt&gt; so all log files can be created.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Run &lt;tt class="docutils literal"&gt;find log &lt;span class="pre"&gt;-type&lt;/span&gt; d &amp;gt; &lt;span class="pre"&gt;dir-to-create&lt;/span&gt;&lt;/tt&gt; to save a list of the directories you will need.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Run &lt;tt class="docutils literal"&gt;find log &lt;span class="pre"&gt;-type&lt;/span&gt; f &amp;gt; &lt;span class="pre"&gt;files-to-create&lt;/span&gt;&lt;/tt&gt; to save a list of the files you will need.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Stop the container and destroy them.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Delete the folder: &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-rf&lt;/span&gt; log&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the directories:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; dir in &lt;span class="k"&gt;$(&lt;/span&gt;cat dir-to-create&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    mkdir -p &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;dir&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the files:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="k"&gt;$(&lt;/span&gt;cat files-to-create&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    touch &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Fix the permissions (run the commands as root):&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;To change the owner: &lt;tt class="docutils literal"&gt;find log &lt;span class="pre"&gt;-type&lt;/span&gt; f &lt;span class="pre"&gt;-exec&lt;/span&gt; chown 100032:100032 {} \;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;To give write access to the group: &lt;tt class="docutils literal"&gt;find log &lt;span class="pre"&gt;-type&lt;/span&gt; f &lt;span class="pre"&gt;-exec&lt;/span&gt; chmod g=rw {} \;&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="unix-sockets"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Unix sockets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I guess you now see how to improve the solution described in &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Feb/15/docker-unix-socket/"&gt;my previous article&lt;/a&gt;. Since we can forsee for a given uid and gid in a container to which uid and gid it will map to in the filesystem, what we need to do is:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Change the uid and gid in the containers so they are the same. For instance &lt;tt class="docutils literal"&gt;usermod &lt;span class="pre"&gt;-u&lt;/span&gt; 60 uwsgi&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;groupmod &lt;span class="pre"&gt;-g&lt;/span&gt; 60 uwsgi&lt;/tt&gt;. This will map to 100059 in the host.&lt;/li&gt;
&lt;li&gt;Create a group with gid 100059 on the host.&lt;/li&gt;
&lt;li&gt;Put the proper user in the newly created group.&lt;/li&gt;
&lt;li&gt;Give permission on the socket to the group.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a bit easier than before since we only have to do the operation once per machine and we can share without any issues the image of the containers since it is the kernel that will do the mapping dynamically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; you can't just rely on ACLs here, since the uid and gid of all containers that will use the socket need to be the same. You can however use ACLs to give permissions to the socket to a user of the host.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="external-links"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;External links&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://blog.yadutaf.fr/2016/04/14/docker-for-your-users-introducing-user-namespace/"&gt;Docker for your users - Introducing user namespace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://success.docker.com/KBase/Introduction_to_User_Namespaces_in_Docker_Engine"&gt;Introduction to User Namespaces in Docker Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://bencane.com/2012/05/27/acl-using-access-control-lists-on-linux/"&gt;ACL: Using Access Control Lists on Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's it. If you have a question or a remark, please leave a comment below.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="Docker"></category><category term="Unix"></category></entry><entry><title>Docker compose tips</title><link href="//www.jujens.eu/posts/2017/Jun/11/docker-compose/" rel="alternate"></link><published>2017-06-11T00:00:00+02:00</published><updated>2017-06-11T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-06-11:/posts/2017/Jun/11/docker-compose/</id><summary type="html">&lt;p&gt;For my tips about docker, go &lt;a class="reference external" href="//www.jujens.eu/posts/2015/May/24/docker/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-docker-compose-override-yml" id="id1"&gt;Use docker-compose.override.yml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="use-docker-compose-override-yml"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Use docker-compose.override.yml&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As describe &lt;a class="reference external" href="https://docs.docker.com/compose/extends"&gt;here&lt;/a&gt;, if you create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.override.yml&lt;/span&gt;&lt;/tt&gt; next to your &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.yml&lt;/span&gt;&lt;/tt&gt;, you can override or add values to the docker file. This file is loaded by default. To ignore it …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;For my tips about docker, go &lt;a class="reference external" href="//www.jujens.eu/posts/2015/May/24/docker/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-docker-compose-override-yml" id="id1"&gt;Use docker-compose.override.yml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="use-docker-compose-override-yml"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Use docker-compose.override.yml&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As describe &lt;a class="reference external" href="https://docs.docker.com/compose/extends"&gt;here&lt;/a&gt;, if you create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.override.yml&lt;/span&gt;&lt;/tt&gt; next to your &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.yml&lt;/span&gt;&lt;/tt&gt;, you can override or add values to the docker file. This file is loaded by default. To ignore it, you must use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--ignore-override&lt;/span&gt;&lt;/tt&gt; option.&lt;/p&gt;
&lt;p&gt;For instance, with this &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.yml&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'2'&lt;/span&gt;

&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;example/my_web_app:latest&lt;/span&gt;
  &lt;span class="nt"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;db&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;cache&lt;/span&gt;

&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;postgres:latest&lt;/span&gt;

&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;redis:latest&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;and this &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.override.yml&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'2'&lt;/span&gt;

&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="s"&gt;'.:/code'&lt;/span&gt;
  &lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;8883:80&lt;/span&gt;

&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;5432:5432&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;when you run &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose&lt;/span&gt; up&lt;/tt&gt;, it will be like you used this  &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.yml&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'2'&lt;/span&gt;

&lt;span class="nt"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;example/my_web_app:latest&lt;/span&gt;
  &lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="s"&gt;'.:/code'&lt;/span&gt;
  &lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;883:80&lt;/span&gt;
  &lt;span class="nt"&gt;links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;db&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;cache&lt;/span&gt;

&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;postgres:latest&lt;/span&gt;
  &lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;5432:5432&lt;/span&gt;

&lt;span class="nt"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;redis:latest&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Docker"></category><category term="Docker compose"></category></entry><entry><title>Create python virtual enviroments on Windows</title><link href="//www.jujens.eu/posts/2017/Jun/11/venv-windows/" rel="alternate"></link><published>2017-06-11T00:00:00+02:00</published><updated>2017-06-11T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-06-11:/posts/2017/Jun/11/venv-windows/</id><summary type="html">&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Before creating the venv you will need to open a PowerShell terminal as root and run the commands below to allow the script that activates the virtual env to run:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
cd ..
Set-ExecutionPolicy Unrestricted
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the venv. Run in a terminal as a normal user: &lt;tt class="docutils literal"&gt;python3 &lt;span class="pre"&gt;-m&lt;/span&gt; venv .venv&lt;/tt&gt; If the …&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Before creating the venv you will need to open a PowerShell terminal as root and run the commands below to allow the script that activates the virtual env to run:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
cd ..
Set-ExecutionPolicy Unrestricted
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Create the venv. Run in a terminal as a normal user: &lt;tt class="docutils literal"&gt;python3 &lt;span class="pre"&gt;-m&lt;/span&gt; venv .venv&lt;/tt&gt; If the creation fails due to &lt;tt class="docutils literal"&gt;python3 not found&lt;/tt&gt;, check that:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;python3 was added to your your PATH during install.&lt;/li&gt;
&lt;li&gt;Make a copy of your &lt;tt class="docutils literal"&gt;python.exe&lt;/tt&gt; executable into &lt;tt class="docutils literal"&gt;python3.exe&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Enable the venv: &lt;tt class="docutils literal"&gt;.venv\Scripts\activate&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Install the dependencies: &lt;tt class="docutils literal"&gt;pip install &lt;span class="pre"&gt;-r&lt;/span&gt; requires.txt&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Install the tests dependencies: &lt;tt class="docutils literal"&gt;pip install &lt;span class="pre"&gt;-r&lt;/span&gt; tests_requires.txt&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To install libraries that requires compiled files (like &lt;a class="reference external" href="http://lxml.de"&gt;lxml&lt;/a&gt;) you can use the wheel files. Most libraries have such a file on pypi so you can install them directly with pip. If not, check &lt;a class="reference external" href="http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml"&gt;this site&lt;/a&gt; to find the proper wheel file for your platform and your version of Python. Then to install it, download it and run &lt;tt class="docutils literal"&gt;pip install \path\to\the\weeh.whl&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category></entry><entry><title>Use squid and squidGuard to redirect all URLs from a domain to another one</title><link href="//www.jujens.eu/posts/en/2017/Jun/09/redirect-url-squid/" rel="alternate"></link><published>2017-06-09T00:00:00+02:00</published><updated>2017-06-09T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-06-09:/posts/en/2017/Jun/09/redirect-url-squid/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-squid" id="id1"&gt;Configure squid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-squidguard" id="id2"&gt;Configure squidGuard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#activate-squid" id="id3"&gt;Activate squid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;You may find yourself in a situation where you will need to redirect all URLs from a domain (lets say www.example.com) to another one (lets say www.example.org). This can be done with squid, a proxy server, and squidGuard, an …&lt;/p&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-squid" id="id1"&gt;Configure squid&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configure-squidguard" id="id2"&gt;Configure squidGuard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#activate-squid" id="id3"&gt;Activate squid&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;You may find yourself in a situation where you will need to redirect all URLs from a domain (lets say www.example.com) to another one (lets say www.example.org). This can be done with squid, a proxy server, and squidGuard, an extension to squid designed to do redirections. In this article I will deal only with redirections of HTTP requests made to that domain.&lt;/p&gt;
&lt;p&gt;First install &lt;tt class="docutils literal"&gt;squid&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;squidGuard&lt;/tt&gt; on your machine (you should be able to find packages for them in the repository of your distribution).&lt;/p&gt;
&lt;div class="section" id="configure-squid"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Configure squid&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We need to tweak a bit the default configuration for it to fit our needs. The config file should be located at &lt;tt class="docutils literal"&gt;/etc/squid/squid.conf&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;First we need to disable the &lt;tt class="docutils literal"&gt;forwarded_for&lt;/tt&gt; feature by adding &lt;tt class="docutils literal"&gt;forwarded_for off&lt;/tt&gt; in the config file. We also need to the name of the proxy with &lt;tt class="docutils literal"&gt;visible_hostname fastolfe.localdomain&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Then we need to configure the program used to rewrite the URL (you may need to change the path to the &lt;tt class="docutils literal"&gt;squidGuard&lt;/tt&gt; executable and config file): &lt;tt class="docutils literal"&gt;url_rewrite_program /usr/bin/squidGuard &lt;span class="pre"&gt;-c&lt;/span&gt; /etc/squid/squidGuard.conf&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;At last but not least, we must allow all connections that are not HTTP or that are on different ports to be passed untouched by the proxy. To achieve that, we need to add the following ACLs (add them below the other ones and before &lt;tt class="docutils literal"&gt;acl CONNECT method CONNECT&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="code squid literal-block"&gt;
&lt;span class="k"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Safe_ports&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;993&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c"&gt;# secured imap&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Safe_ports&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;587&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c"&gt;# secured smpt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Safe_ports&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c"&gt;# default smtp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Safe_ports&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;465&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c"&gt;# gmail smtp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Safe_ports&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;53&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c"&gt;# DNS&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We then need to change the &lt;tt class="docutils literal"&gt;http_access&lt;/tt&gt; rule to allow not only HTTPS on port 443 but all the other ones. To do that, replace &lt;tt class="docutils literal"&gt;http_access deny CONNECT !SSL_ports&lt;/tt&gt; by &lt;tt class="docutils literal"&gt;http_access deny CONNECT !Safe_ports&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Since all your HTTP request will go through the proxy, you may want to disable the log to prevent them to use lot of disk space. To do that, add to the config file:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
access_log none
cache_log none
cache_log none
logfile_rotate 0
&lt;/pre&gt;
&lt;p&gt;You can download my full configuration file &lt;a class="reference external" href="//www.jujens.eu/static/squid/squid.conf"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="configure-squidguard"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Configure squidGuard&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We will first need to write the main configuration file that should be at &lt;tt class="docutils literal"&gt;/etc/squid/squidGuard.conf&lt;/tt&gt;. If the file already exists, I advise you to replace its content by the code below. You will have to adapt it to mach your needs.&lt;/p&gt;
&lt;pre class="code squid literal-block"&gt;
&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# CONFIG FILE FOR SQUIDGUARD&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Where to store the database of the rules.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;dbhome&lt;span class="w"&gt; &lt;/span&gt;/etc/squid&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Log dir. You may need to create the directory manually, create the /var/log/squidGuard/squidGuard.log file and give it to the squid user.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;logdir&lt;span class="w"&gt; &lt;/span&gt;/var/log/squidGuard&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# REWRITE RULES:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;rew&lt;span class="w"&gt; &lt;/span&gt;example&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;# Rewrite (replace in the URL) www.example.com by www.example.org&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;s&amp;#64;://www.example.com/&amp;#64;://www.example.org/&amp;#64;i&lt;span class="w"&gt;
&lt;/span&gt;}&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# SOURCE ADDRESSES:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;local&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;# Define what source addresses the proxy must proxy. Here we limit ourselves to local host.&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;ip&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;127.0.0.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;}&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# DESTINATION CLASSES:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;dest&lt;span class="w"&gt; &lt;/span&gt;local&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt;
&lt;/span&gt;}&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="k"&gt;acl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="no"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# Rewrite the URL based on the example rewrite rule.&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;rewrite&lt;span class="w"&gt; &lt;/span&gt;example&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# Don't block any addresses, configure the proxy to pass everything.&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;pass&lt;span class="w"&gt;        &lt;/span&gt;local&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;all&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;}
&lt;/pre&gt;
&lt;p&gt;To test the configuration run:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'http://www.example.com/some/url - - GET'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; squidGuard -c squidGuard.conf -d
&lt;/pre&gt;
&lt;p&gt;You should get something like:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
2017-06-10 17:07:41 [22756] New setting: dbhome: /etc/squid
2017-06-10 17:07:41 [22756] New setting: logdir: /var/log/squidGuard
2017-06-10 17:07:41 [22756] destblock local missing active content, set inactive
2017-06-10 17:07:41 [22756] squidGuard 1.4 started (1497107261.140)
2017-06-10 17:07:41 [22756] squidGuard ready for requests (1497107261.141)
2017-06-10 17:07:41 [22756] source not found
2017-06-10 17:07:41 [22756] no ACL matching source, using default
OK rewrite-url=&amp;quot;http://www.example.org/some/url&amp;quot;
2017-06-10 17:07:41 [22756] squidGuard stopped (1497107261.141)
&lt;/pre&gt;
&lt;p&gt;If you use another URL, you should get this response:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
2017-06-10 17:07:49 [22759] New setting: dbhome: /etc/squid
2017-06-10 17:07:49 [22759] New setting: logdir: /var/log/squidGuard
2017-06-10 17:07:49 [22759] destblock local missing active content, set inactive
2017-06-10 17:07:49 [22759] squidGuard 1.4 started (1497107269.252)
2017-06-10 17:07:49 [22759] squidGuard ready for requests (1497107269.252)
2017-06-10 17:07:49 [22759] source not found
2017-06-10 17:07:49 [22759] no ACL matching source, using default
ERR
2017-06-10 17:07:49 [22759] squidGuard stopped (1497107269.252)
&lt;/pre&gt;
&lt;p&gt;You can download my full configuration file &lt;a class="reference external" href="//www.jujens.eu/static/squid/squidGuard.conf"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="activate-squid"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Activate squid&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can now enable and start the proxy: &lt;tt class="docutils literal"&gt;systemctl enable squid&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;systemctl start squid&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;You now need to configure your software to use it. For instance, if you use NetworkManager, to make all requests go through it:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Open the network settings.&lt;/li&gt;
&lt;li&gt;Go under &lt;em&gt;Network proxy&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;Manual&lt;/em&gt; in &lt;em&gt;Method&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Fill the first field of &lt;em&gt;HTTP Proxy&lt;/em&gt; with &lt;tt class="docutils literal"&gt;localhost&lt;/tt&gt; and put &lt;tt class="docutils literal"&gt;3128&lt;/tt&gt; in the second one.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That's it. If you have a problem or a question, please leave a comment.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="squid"></category><category term="Linux"></category></entry><entry><title>Require valid-user on Apache only for some request types</title><link href="//www.jujens.eu/posts/en/2017/Mar/29/apache-require-auth-request-type/" rel="alternate"></link><published>2017-03-29T00:00:00+02:00</published><updated>2017-03-29T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-03-29:/posts/en/2017/Mar/29/apache-require-auth-request-type/</id><content type="html">&lt;p&gt;You can use the &lt;tt class="docutils literal"&gt;Limit&lt;/tt&gt; directive like this:&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="nb"&gt;AuthType&lt;/span&gt; basic
&lt;span class="nb"&gt;AuthName&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Restricted area&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;AuthUserFile&lt;/span&gt; &lt;span class="sx"&gt;/var/www/passwd&lt;/span&gt;
&lt;span class="nb"&gt;Require&lt;/span&gt; valid-user
&lt;span class="c"&gt;# Only GET and OPTIONS request are allowed without authentication.&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Limit&lt;/span&gt; &lt;span class="s"&gt;GET OPTIONS&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;Require&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt; granted
&lt;span class="nt"&gt;&amp;lt;/Limit&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="apache"></category></entry><entry><title>Mon passage à LineageOS</title><link href="//www.jujens.eu/posts/2017/Mar/29/switch-to-lineageos/" rel="alternate"></link><published>2017-03-29T00:00:00+02:00</published><updated>2017-03-29T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-03-29:/posts/2017/Mar/29/switch-to-lineageos/</id><summary type="html">&lt;p&gt;Tout d'abord, je présente un projet intéressant : &lt;a class="reference external" href="https://f-droid.org/repository/browse/?fdfilter=Oandbackup&amp;amp;fdid=dk.jens.backup"&gt;oandbackup&lt;/a&gt; que j'ai découvert via &lt;a class="reference external" href="https://tuxicoman.jesuislibre.net/2017/02/passage-de-cyanogen-a-lineageos.html?pk_campaign=feed&amp;amp;amp;pk_kwd=passage-de-cyanogen-a-lineageos"&gt;cet article&lt;/a&gt;. oandbanck vous permet de sauvegarder les APK installés sur votre téléphone pour pouvoir les réinstaller une fois la mise à jour effectuée. Malheureusement, suite à un problème lors de la mise à jour, j'ai dû formater …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Tout d'abord, je présente un projet intéressant : &lt;a class="reference external" href="https://f-droid.org/repository/browse/?fdfilter=Oandbackup&amp;amp;fdid=dk.jens.backup"&gt;oandbackup&lt;/a&gt; que j'ai découvert via &lt;a class="reference external" href="https://tuxicoman.jesuislibre.net/2017/02/passage-de-cyanogen-a-lineageos.html?pk_campaign=feed&amp;amp;amp;pk_kwd=passage-de-cyanogen-a-lineageos"&gt;cet article&lt;/a&gt;. oandbanck vous permet de sauvegarder les APK installés sur votre téléphone pour pouvoir les réinstaller une fois la mise à jour effectuée. Malheureusement, suite à un problème lors de la mise à jour, j'ai dû formater ma carte SD, du coup, je n'ai pu tester que la sauvegarde et pas la restauration. Mais d'après ce que j'ai lu, ça fonctionne très bien.&lt;/p&gt;
&lt;p&gt;Concernant l'installation à proprement parler : j'avais déjà tenté une installation début février avec une nightly pour mon galaxy s2. Ça c'était mal passé : l'installation n'arrivait pas à se terminer. Après plusieurs tentatives infructueuses, les builds de cyanogenmod n'étant plus disponibles, j'ai fini par installer une vieille build de replicant pour pouvoir passer des appels et recevoir des SMS. Comme le projet lineageos a pas mal bougé (et que la build de replicant était vraiment vieille), j'ai retenté le week-end dernier une installation. J'ai eu quelques soucis mais j'ai réussi à les contourner. Voici ce que j'ai fait :&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Télécharger une image récente : &lt;a class="reference external" href="https://download.lineageos.org/"&gt;https://download.lineageos.org/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Télécharger l'utilitaire SU : &lt;a class="reference external" href="https://download.lineageos.org/extras"&gt;https://download.lineageos.org/extras&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Copier les fichiers sur la carte SD&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Installer TWRP (le mode recovery) : c'est à partir de là que les choses ont commencés à ce gâter. J'ai tenté la commande issue de la documentation:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
heimdall flash --KERNEL twrp-3.1.0-0-i9100.img --no-reboot
&lt;/pre&gt;
&lt;p&gt;Malheureusement, impossible de démarrer sous TWRP : le téléphone démarrait sous l''ancien recovery. J'ai bien tenté &lt;tt class="docutils literal"&gt;heimdall flash &lt;span class="pre"&gt;--KERNEL&lt;/span&gt; &lt;span class="pre"&gt;twrp-3.1.0-0-i9100.img&lt;/span&gt; &lt;span class="pre"&gt;--no-reboot&lt;/span&gt;&lt;/tt&gt; (ce que je faisais avec mes anciennes recovery) mais là, impossible de démarrer. D'après ce que j'ai compris, cela vient du fait que TWRP est plus qu'un simple mode recovery, il a besoin d'un noyau pour démarrer. La solution, c'est d'utiliser le noyau contenu dans l'image LineageOS pour pouvoir démarrer en mode recovery. Pour cela :&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Dézipper &lt;tt class="docutils literal"&gt;boot.img&lt;/tt&gt; de l'image.&lt;/li&gt;
&lt;li&gt;Lancer avec le téléphone en mode &lt;em&gt;téléchargement&lt;/em&gt; :&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="code bash literal-block"&gt;
heimdall flash --KERNEL boot.img --RECOVERY twrp-3.1.0-0-i9100.img
&lt;/pre&gt;
&lt;p&gt;Normalement, maintenant, le téléphone peut démarrer en mode recovery.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Effacer les &amp;quot;caches&amp;quot; dalvik, data, system, et cache.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Lancer l'installation du zip. Dans mon cas, l'installation se bloquait aux trois quart environ. En regardant les messages, j'ai vu : &lt;tt class="docutils literal"&gt;Failed to mount '/system'&lt;/tt&gt;. J'ai testé pas mal de choses (revider les caches, changer le système de fichier avec parted, …) mais rien n'y a fait. Heureusement, j'ai fini par trouver &lt;a class="reference external" href="https://www.reddit.com/r/LineageOS/comments/5zf0yx/help_installing_lineageos_on_i9100_need_new_pit/"&gt;ce thread reddit&lt;/a&gt; qui donne la solution : réparer le fichier PIT du téléphone. Pour cela, &lt;a class="reference external" href="/static/lineageos/I9100_1.5GB-System_6GB-Data_512MB-Preload_by-the.gangster.pit"&gt;télécharger le PIT &amp;quot;qui va bien&amp;quot;&lt;/a&gt; (ou via &lt;a class="reference external" href="https://www.androidfilehost.com/?fid=24591000424954843"&gt;le lien original&lt;/a&gt;). Ensuite, lancer en mode &lt;em&gt;téléchargement&lt;/em&gt; (où &lt;tt class="docutils literal"&gt;boot.img&lt;/tt&gt; est le noyau de LineageOS dézipper précédemment):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
heimdall flash --repartition --pit I9100_1.5GB-System_6GB-Data_512MB-Preload_by-the.gangster.pit --KERNEL boot.img --RECOVERY twrp-3.1.0-0-i9100.img
&lt;/pre&gt;
&lt;p&gt;À ce stade, l'installation du zip devrait fonctionner (j'ai revidé les caches avant on ne sait jamais).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Installer su&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Redémarrer&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Normalement tout va bien&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Malheureusement, je ne sais plus à quel moment j'ai dû effacer la carte SD (je n'ai pas pris de notes pensant pouvoir écrire ce billet plus tôt). Mais de mémoire, c'était évident donc j'espère que pour vous aussi. Et si vous rencontrez un problème, vous pouvez laisser un commentaire !&lt;/p&gt;
</content><category term="Blog"></category><category term="Android"></category><category term="LineageOS"></category></entry><entry><title>Angular2 and SVG</title><link href="//www.jujens.eu/posts/en/2017/Feb/21/angular2-svg/" rel="alternate"></link><published>2017-02-21T00:00:00+01:00</published><updated>2017-02-21T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-02-21:/posts/en/2017/Feb/21/angular2-svg/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I use the &lt;a class="reference external" href="https://aurelia.io"&gt;Aurelia framework&lt;/a&gt;, a competitor of Angular2. I wrote &lt;a class="reference external" href="/tag/aurelia.html"&gt;several articles about Aurelia&lt;/a&gt;. I am not an expert with Angular2. If you spot a mistake, please leave a comment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2017-03-06:&lt;/strong&gt; Give the solution of how to use binding with SVG attributes. Thanks &lt;a class="reference external" href="/posts/en/2017/Feb/21/angular2-svg/#isso-111"&gt;NexusVI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;a class="reference external" href="https://medium.com/hashnode/rob-eisenberg-on-aurelia-and-how-it-stacks-up-against-angular-2-and-react-82721d714449"&gt;an interview …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; I use the &lt;a class="reference external" href="https://aurelia.io"&gt;Aurelia framework&lt;/a&gt;, a competitor of Angular2. I wrote &lt;a class="reference external" href="/tag/aurelia.html"&gt;several articles about Aurelia&lt;/a&gt;. I am not an expert with Angular2. If you spot a mistake, please leave a comment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2017-03-06:&lt;/strong&gt; Give the solution of how to use binding with SVG attributes. Thanks &lt;a class="reference external" href="/posts/en/2017/Feb/21/angular2-svg/#isso-111"&gt;NexusVI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;a class="reference external" href="https://medium.com/hashnode/rob-eisenberg-on-aurelia-and-how-it-stacks-up-against-angular-2-and-react-82721d714449"&gt;an interview&lt;/a&gt; about a year old, Rob Eisenberg, the creator of the &lt;a class="reference external" href="https://aurelia.io"&gt;Aurelia framework&lt;/a&gt;, said:&lt;/p&gt;
&lt;blockquote&gt;
Over a year ago the Angular 2 team introduced their symbolic binding syntax. While that was technically standards compliant HTML, it was pointed out by the community that it was not compliant SVG (I have not confirmed that myself). Although members of the community pointed this out, the Angular 2 team made no changes to their design.&lt;/blockquote&gt;
&lt;p&gt;Since I recently completed a book about Angular2 and that I heavily use SVG in my applications, I wanted to test it myself. So I created an app with the cli (you can install it with &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;-g&lt;/span&gt; &lt;span class="pre"&gt;angular-cli&amp;#64;1.0.0-beta.22-1&lt;/span&gt;&lt;/tt&gt;). Nothing fancy, just &lt;tt class="docutils literal"&gt;ng new &lt;span class="pre"&gt;test-svg&lt;/span&gt;&lt;/tt&gt;. I then created a small SVG with Inkscape (it just contains a rectangle) and copied it into the template of the application.&lt;/p&gt;
&lt;p&gt;I ran &lt;tt class="docutils literal"&gt;ng serve&lt;/tt&gt; to build the application, opened it in a browser and BOOM, first error:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
zone.js:388Unhandled Promise rejection: Template parse errors:
':sodipodi:namedview' is not a known element:
&lt;/pre&gt;
&lt;p&gt;From what I know, Angular2 has its own HTML parser (mostly to parse camel cased syntax like &lt;tt class="docutils literal"&gt;ngIf&lt;/tt&gt; which is not HTML compliant) and it fails if it encounters an HTML tag or attribute it doesn't know. While it's nice to help you spot typos in the name of your component, if a piece of HTML or SVG has a non standard tag or attribute, it will crash. Here it is not a big deal, my SVG is small, I can get rid of &lt;tt class="docutils literal"&gt;&amp;lt;sodipodi:namedview /&amp;gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&amp;lt;metadata /&amp;gt;&lt;/tt&gt;. But in one of my application, I need to display user uploaded SVGs. Once uploaded, I add AngularJS tags so I can display only certain elements of it depending on actions of the user. These SVGs will contain non standard tags like the Inkscape ones. How can I get rid of all of them so that Angular2 is happy? Whitelist? But what should I put in it? Blacklist? Same question. There are many SVG software out there, each may have its quirks.&lt;/p&gt;
&lt;p&gt;This made me wonder: what if I use a brand new HTML 5.1 tag? Will it crash? I tried the code below, and it worked. I guess the parser is already 5.1 compliant. But to support 5.2 you will probably need to update Angular.&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; // Start Of A New Accordion Element
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; TITLE OF ACCORDION ELEMENT &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    // Anything Here Will Be Displayed After Accordion Is Toggled To Open
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est.
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;details&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now that we have a working SVG, it is time to add Angular2 markup. Let's start simple and add an &lt;tt class="docutils literal"&gt;ngIf&lt;/tt&gt; attribute to show/hide the SVG based on the value of a variable:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngIf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;showSvg&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Let's add a button to toggle the value of the SVG:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;toggleSvg&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Toggle SVG&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And the &lt;tt class="docutils literal"&gt;toggleSvg&lt;/tt&gt; function:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;toggleSvg&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showSvg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;showSvg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And this works. The SVG is correctly displayed/hidden when I press the button.&lt;/p&gt;
&lt;p&gt;Next step: hide the SVG when I click on the rectangle. Let's add the proper attribute:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;toggleSvg&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If I click on the rectangle, the SVG is hidden as expected.&lt;/p&gt;
&lt;p&gt;Next step: display multiple rectangles. Let's add a &lt;tt class="docutils literal"&gt;rectTops&lt;/tt&gt; property to the component. It contains the y value for SVG rectangles. We will loop over it to display a rectangle for each value (and in a moment, we will try to bind the value to the &lt;tt class="docutils literal"&gt;y&lt;/tt&gt; attribute of our rectangles).&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;rectTops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;let top of rectTops&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;hideSvg&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If we inspect the DOM, we see all the rectangles in it. Now, let's use the value:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;let top of rectTops&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;hideSvg&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And it fails:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
Unhandled Promise rejection: Template parse errors:
Can't bind to 'y' since it isn't a known property of ':svg:rect'. (&amp;quot;
&lt;/pre&gt;
&lt;p&gt;You may say, no problem, let's use the mustache notation instead:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;let top of rectTops&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;hideSvg&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;{{ top }}&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;No luck, it crashes too with the same error. And &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;bind-y=&amp;quot;top&amp;quot;&lt;/span&gt;&lt;/tt&gt;? No luck either, still the same error.&lt;/p&gt;
&lt;p&gt;It appears that the correct way to do this is:&lt;/p&gt;
&lt;pre class="code HTML literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;let top of rectTops&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;hideSvg&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;attr&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;
   &lt;span class="err"&gt;…&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Thanks &lt;a class="reference external" href="/posts/en/2017/Feb/21/angular2-svg/#isso-111"&gt;NexusVI&lt;/a&gt;.&lt;/p&gt;
</content><category term="Blog"></category><category term="Angular2"></category><category term="SVG"></category></entry><entry><title>Use Unix sockets with Docker</title><link href="//www.jujens.eu/posts/en/2017/Feb/15/docker-unix-socket/" rel="alternate"></link><published>2017-02-15T00:00:00+01:00</published><updated>2017-02-15T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-02-15:/posts/en/2017/Feb/15/docker-unix-socket/</id><summary type="html">&lt;p&gt;By default, you are supposed to use TCP sockets to communicate with your applications running in Docker. But what if you want to use Unix sockets instead? The answer is you can: you make the application create the socket file in a volume and set the proper permissions to it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;By default, you are supposed to use TCP sockets to communicate with your applications running in Docker. But what if you want to use Unix sockets instead? The answer is you can: you make the application create the socket file in a volume and set the proper permissions to it. You can them use it for your webserver to talk to your application or for cross container communications. The tricky part is to set the proper permissions on the socket.&lt;/p&gt;
&lt;p&gt;Let's say you are creating a Python web application running in a container with &lt;a class="reference external" href="http://uwsgi-docs.readthedocs.io/"&gt;UWSGI&lt;/a&gt;. It will run in the container as the &lt;tt class="docutils literal"&gt;uwsig&lt;/tt&gt; user. You want it to use a Unix socket to communicate with your nginx webserver running on the host under the &lt;tt class="docutils literal"&gt;nginx&lt;/tt&gt; user. You need to the socket:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;To belong to the &lt;tt class="docutils literal"&gt;uwsgi&lt;/tt&gt; user inside the container so your application can use it.&lt;/li&gt;
&lt;li&gt;To belong to the &lt;tt class="docutils literal"&gt;nginx&lt;/tt&gt; user outside it, so nginx can use it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The question is, how do we fullfil these two requirements? First, let's explain how file ownership works.&lt;/p&gt;
&lt;p&gt;In Unix each file has a owner and a group. You can see them with &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ ls -l
-rw-rw-r--. 1 jujens jujens 366 Sep 12 14:13 README.md
&lt;/pre&gt;
&lt;p&gt;Here we have a file named &lt;tt class="docutils literal"&gt;README.md&lt;/tt&gt; that belongs to a user named &lt;tt class="docutils literal"&gt;jujens&lt;/tt&gt; and a group named &lt;tt class="docutils literal"&gt;jujens&lt;/tt&gt;. What you must know is: the names are just the human readable version of these attributes. They are encoded in the filesystem as numbers respectively named uid and gid.&lt;/p&gt;
&lt;p&gt;So what we need to do, is make sure that both the &lt;tt class="docutils literal"&gt;nginx&lt;/tt&gt; user (in the host system) and the &lt;tt class="docutils literal"&gt;uwsgi&lt;/tt&gt; user (in the container) have the same uid (and gid). Depending on where we do &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-l&lt;/span&gt;&lt;/tt&gt; we'll get different human readable names but the permissions will be correct.&lt;/p&gt;
&lt;p&gt;To do that, we need 3 commands:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;id&lt;/tt&gt; to get the uid and gid of a user: &lt;tt class="docutils literal"&gt;id &lt;span class="pre"&gt;-u&lt;/span&gt;&lt;/tt&gt; will give you the uid of the current user and &lt;tt class="docutils literal"&gt;id &lt;span class="pre"&gt;-g&lt;/span&gt;&lt;/tt&gt; the gid of the current user. You can pass an optional username to get the uid and gid for a specific user: &lt;tt class="docutils literal"&gt;id &lt;span class="pre"&gt;-u&lt;/span&gt; nginx&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;usermod&lt;/tt&gt; to change the uid of a user: &lt;tt class="docutils literal"&gt;usermod &lt;span class="pre"&gt;-u&lt;/span&gt; &amp;lt;NEW_ID&amp;gt; &amp;lt;USER&amp;gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;groupmod&lt;/tt&gt; to change the gid of a user: &lt;tt class="docutils literal"&gt;groupmod &lt;span class="pre"&gt;-g&lt;/span&gt; &amp;lt;NEW_ID&amp;gt; &amp;lt;GROUP&amp;gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now we just have to use them correctly. First, let's create a &lt;tt class="docutils literal"&gt;setup.sh&lt;/tt&gt; script next to your Dockerfile. It will change the uid and gid for the &lt;tt class="docutils literal"&gt;uwsgi&lt;/tt&gt; user inside the container. It takes two parameters, the uid and the gui:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/bash
&lt;/span&gt;&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="ch"&gt;&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="c1"&gt;# Quit on error.
&lt;/span&gt;&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -e
&lt;span class="ln"&gt; 5 &lt;/span&gt;&lt;span class="c1"&gt;# Treat undefined variables as errors.
&lt;/span&gt;&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt; -u
&lt;span class="ln"&gt; 7 &lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; main &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;    &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;uwsgi_uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;    &lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="nv"&gt;uwsgi_gid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;    &lt;span class="c1"&gt;# Change the uid
&lt;/span&gt;&lt;span class="ln"&gt;14 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uwsgi_uid&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;        usermod -u &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uwsgi_uid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; uwsgi
&lt;span class="ln"&gt;16 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;    &lt;span class="c1"&gt;# Change the gid
&lt;/span&gt;&lt;span class="ln"&gt;18 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uwsgi_gid&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;        groupmod -g &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uwsgi_gid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; uwsgi
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;    &lt;span class="c1"&gt;# Setup permissions on the run directory where the sockets will be
&lt;/span&gt;&lt;span class="ln"&gt;23 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="c1"&gt;# created, so we are sure the app will have the rights to create them.
&lt;/span&gt;&lt;span class="ln"&gt;24 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;    &lt;span class="c1"&gt;# Make sure the folder exists.
&lt;/span&gt;&lt;span class="ln"&gt;26 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    mkdir /var/run/uwsgi
&lt;span class="ln"&gt;27 &lt;/span&gt;    &lt;span class="c1"&gt;# Set owner.
&lt;/span&gt;&lt;span class="ln"&gt;28 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    chown root:uwsgi /var/run/uwsgi
&lt;span class="ln"&gt;29 &lt;/span&gt;    &lt;span class="c1"&gt;# Set permissions.
&lt;/span&gt;&lt;span class="ln"&gt;30 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    chmod &lt;span class="nv"&gt;u&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rwX,g&lt;span class="o"&gt;=&lt;/span&gt;rwX,o&lt;span class="o"&gt;=&lt;/span&gt;--- /var/run/uwsgi
&lt;span class="ln"&gt;31 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;main &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In the Dockerfile, we need to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Define the variables we what to pass to the script.&lt;/li&gt;
&lt;li&gt;Copy the script in the container.&lt;/li&gt;
&lt;li&gt;Pass the correct variables to the script.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To do so, we need the lines below (&lt;em&gt;note:&lt;/em&gt; this Docker file is not complete, I just present here the relevant lines for what we need to do):&lt;/p&gt;
&lt;pre class="code Docker literal-block"&gt;
&lt;span class="c"&gt;# Define the variables available.&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt; uwsgi_uid
&lt;span class="k"&gt;ARG&lt;/span&gt; uwsgi_gid

&lt;span class="c"&gt;# Copy the script.&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt; setup.sh /

&lt;span class="c"&gt;# Launch setup.sh&lt;/span&gt;
&lt;span class="k"&gt;RUN&lt;/span&gt; bash /setup.sh &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uwsgi_uid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uwsgi_gid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;At this point, all we have to do is use this Dockerfile. I'll describe two ways to use it:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;With the &lt;tt class="docutils literal"&gt;docker&lt;/tt&gt; command.&lt;/li&gt;
&lt;li&gt;With the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose&lt;/span&gt;&lt;/tt&gt; command. To learn more about &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose&lt;/span&gt;&lt;/tt&gt;, see &lt;a class="reference external" href="https://docs.docker.com/compose/"&gt;the documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="directly-with-the-docker-command"&gt;
&lt;h2&gt;Directly with the docker command&lt;/h2&gt;
&lt;p&gt;First we need to build our container with the proper values in our &lt;tt class="docutils literal"&gt;uwsgi_uid&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;uwsgi_gid&lt;/tt&gt; variables. To achieve that, we need to use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--build-arg&lt;/span&gt;&lt;/tt&gt; option (&lt;em&gt;note:&lt;/em&gt; the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$(…)&lt;/span&gt;&lt;/tt&gt; construct allows us to execute a command. &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$(…)&lt;/span&gt;&lt;/tt&gt; will be replaced by the output of the command):&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
docker build --build-arg &lt;span class="nv"&gt;uwsgi_uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -u nginx&lt;span class="k"&gt;)&lt;/span&gt; --build-arg &lt;span class="nv"&gt;uwsgi_gid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -g nginx&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now we can run the application by mounting &lt;tt class="docutils literal"&gt;/var/run/uwsgi&lt;/tt&gt; (the folder in which the socket of our application will be) into a volume so it is accessible by the host:&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
docker run --volume &lt;span class="s2"&gt;&amp;quot;/var/run/myapp/:/var/run/uwsgi/:rw&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And that's it. If something is not clear, please leave a comment.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="with-docker-compose"&gt;
&lt;h2&gt;With docker-compose&lt;/h2&gt;
&lt;p&gt;First we need to create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose.yml&lt;/span&gt;&lt;/tt&gt; file. We need to specify an &lt;tt class="docutils literal"&gt;args&lt;/tt&gt; section inside &lt;tt class="docutils literal"&gt;build&lt;/tt&gt; to define the variables and a &lt;tt class="docutils literal"&gt;volumes&lt;/tt&gt; section inside &lt;tt class="docutils literal"&gt;myapp&lt;/tt&gt; to define the volume:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'2'&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;    &lt;span class="nt"&gt;myapp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;        &lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;            &lt;span class="nt"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;.&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;            &lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;                &lt;span class="nt"&gt;uwsgi_uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;${UWSGI_UID}&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;                &lt;span class="nt"&gt;uwsgi_gid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;${UWSGI_GID}&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;        &lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;always&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;        &lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;        &lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;${SOCKET_DIR}/:/var/run/uwsgi/:rw&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Then we need to export in our shell the &lt;tt class="docutils literal"&gt;UWSGI_UID&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;UWSGI_GID&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;SOCKET_DIR&lt;/tt&gt; variables so &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose&lt;/span&gt;&lt;/tt&gt; can find them.&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;UWSGI_UID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -u nginx&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;UWSGI_GID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;id -g nginx&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;SOCKET_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/var/run/myapp&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Finally, in the same shell, we can launch &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;docker-compose&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code shell literal-block"&gt;
docker-compose up -d
&lt;/pre&gt;
&lt;p&gt;And that's it. If something is not clear, please leave a comment.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="Docker"></category><category term="Unix"></category></entry><entry><title>Extraire toutes les images encodées en base64 d'un SVG</title><link href="//www.jujens.eu/posts/2017/Feb/13/extract-images-svg/" rel="alternate"></link><published>2017-02-13T00:00:00+01:00</published><updated>2017-02-13T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-02-13:/posts/2017/Feb/13/extract-images-svg/</id><summary type="html">&lt;p&gt;Récemment, j'ai eu besoin d'intégrer un SVG dans un template Aurelia. Malheureusement, il contenait beaucoup d'images et elles étaient toutes incluses au format base64. Cela rendait le fichier quasiment inutilisable avec de gros pâtés qui empêchent de voir le code utile et d'ajouter les attributs «&amp;nbsp;Aurelia&amp;nbsp;» (comme &lt;tt class="docutils literal"&gt;if.bind&lt;/tt&gt;). Heureusement …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Récemment, j'ai eu besoin d'intégrer un SVG dans un template Aurelia. Malheureusement, il contenait beaucoup d'images et elles étaient toutes incluses au format base64. Cela rendait le fichier quasiment inutilisable avec de gros pâtés qui empêchent de voir le code utile et d'ajouter les attributs «&amp;nbsp;Aurelia&amp;nbsp;» (comme &lt;tt class="docutils literal"&gt;if.bind&lt;/tt&gt;). Heureusement, Python (3) est là !&lt;/p&gt;
&lt;p&gt;Le script ci-dessous prend comme paramètre le chemin vers un fichier SVG et va extraire toutes les images encodées en base64 dans le dossier courrant. Le SVG utilisant ces images extraites est sauvegardé dans le dossier courrant avec le nom &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svg-without-images.svg&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;base64&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;b64decode&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;&lt;span class="c1"&gt;# On définit les espaces de nom XML (namespace) qui vont nous permettre de faire des requêtes dans le SVG.&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="n"&gt;NS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="s1"&gt;'svg'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'http://www.w3.org/2000/svg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;    &lt;span class="s1"&gt;'xlink'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'http://www.w3.org/1999/xlink'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_help&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./extract-images-svg.py SVG_FILE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This will extract the images included in b64 in the SVG.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_images_svg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="c1"&gt;# On ouvre le fichier source et on le parse.&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;        &lt;span class="n"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;    &lt;span class="c1"&gt;# On utilise xpath pour trouver toutes les images contenues dans le fichier.&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;    &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;svg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.//svg:image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;namespaces&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;NS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;        &lt;span class="c1"&gt;# On récupère le contenu de l'image.&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{http://www.w3.org/1999/xlink}href'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;        &lt;span class="c1"&gt;# On regarde si l'image est au format base64. Si oui, on extrait le contenu.&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data:image/'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;            &lt;span class="c1"&gt;# On extrait l'image et ses méta-données (seul le format nous intéresse ici).&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;            &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_b64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;';base64,'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;            &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;            &lt;span class="c1"&gt;# On extrait l'image dans le format utilisé avant l'encodage en base64.&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;            &lt;span class="n"&gt;img_file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'img-&lt;/span&gt;&lt;span class="si"&gt;{index}&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{format}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;img_format&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;            &lt;span class="c1"&gt;# On remplace le lien vers l'image extraite.&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{http://www.w3.org/1999/xlink}href'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;            &lt;span class="c1"&gt;# On sauvegarde le fichier.&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'wb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;                &lt;span class="n"&gt;img_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_b64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;    &lt;span class="c1"&gt;# On sauvegarde notre nouveau SVG.&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'svg-without-images.svg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;        &lt;span class="n"&gt;svg_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
&lt;span class="ln"&gt;45 &lt;/span&gt;                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
&lt;span class="ln"&gt;46 &lt;/span&gt;                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;        &lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svg_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;
&lt;span class="ln"&gt;49 &lt;/span&gt;
&lt;span class="ln"&gt;50 &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;51 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;52 &lt;/span&gt;        &lt;span class="n"&gt;print_help&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt;53 &lt;/span&gt;        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;54 &lt;/span&gt;
&lt;span class="ln"&gt;55 &lt;/span&gt;    &lt;span class="n"&gt;extract_images_svg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category><category term="SVG"></category></entry><entry><title>Logger les données d'une requête POST avec apache</title><link href="//www.jujens.eu/posts/2017/Feb/13/log-post-requests-apache/" rel="alternate"></link><published>2017-02-13T00:00:00+01:00</published><updated>2017-02-13T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-02-13:/posts/2017/Feb/13/log-post-requests-apache/</id><summary type="html">&lt;p&gt;D'après le manuel, une façon simple de logger le contenu d'une requête POST (a priori uniquement en développement pour débugger l'application, sinon la taille des logs de production va exploser et on risque de faire fuiter des informations) est d'utiliser le module &lt;a class="reference external" href="https://httpd.apache.org/docs/2.4/fr/mod/mod_dumpio.html"&gt;dumpio&lt;/a&gt;, soit pour Apache 2.4 :&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="c"&gt;# On met …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;D'après le manuel, une façon simple de logger le contenu d'une requête POST (a priori uniquement en développement pour débugger l'application, sinon la taille des logs de production va exploser et on risque de faire fuiter des informations) est d'utiliser le module &lt;a class="reference external" href="https://httpd.apache.org/docs/2.4/fr/mod/mod_dumpio.html"&gt;dumpio&lt;/a&gt;, soit pour Apache 2.4 :&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="c"&gt;# On met les logs dans des fichiers à part pour faciliter la lecture.&lt;/span&gt;
&lt;span class="nb"&gt;CustomLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/httpd/website.log&lt;/span&gt; combined
&lt;span class="nb"&gt;ErrorLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/httpd/website.error.log&lt;/span&gt;

&lt;span class="c"&gt;# On active les logs debug&lt;/span&gt;
&lt;span class="nb"&gt;LogLevel&lt;/span&gt; &lt;span class="k"&gt;debug&lt;/span&gt;

&lt;span class="c"&gt;# On active le module&lt;/span&gt;
&lt;span class="nb"&gt;DumpIOInput&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;DumpIOOutput&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;LogLevel&lt;/span&gt; dumpio:trace7
&lt;/pre&gt;
&lt;p&gt;Malheureusement, je n'ai jamais réussi à le faire fonctionner. Heureusement, il y a un autre module qui permet de faire ça : &lt;tt class="docutils literal"&gt;mod_security&lt;/tt&gt;. Il se configure comme suit :&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="c"&gt;# On active le module.&lt;/span&gt;
&lt;span class="nb"&gt;SecRuleEngine&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;SecAuditEngine&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="c"&gt;# On lui donne un fichier de log.&lt;/span&gt;
&lt;span class="nb"&gt;SecAuditLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/httpd/website-audit.log&lt;/span&gt;
&lt;span class="c"&gt;# On l'autorise à accéder au corps des requêtes.&lt;/span&gt;
&lt;span class="nb"&gt;SecRequestBodyAccess&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="nb"&gt;SecAuditLogParts&lt;/span&gt; ABIFHZ

&lt;span class="c"&gt;# On configure une action par défaut.&lt;/span&gt;
&lt;span class="nb"&gt;SecDefaultAction&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;nolog,noauditlog,allow,phase:2&amp;quot;&lt;/span&gt;

&lt;span class="c"&gt;# On définit une règle qui nous permet de logger le contenu des requêtes POST&lt;/span&gt;
&lt;span class="nb"&gt;SecRule&lt;/span&gt; REQUEST_METHOD &lt;span class="s2"&gt;&amp;quot;^POST$&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;chain,allow,phase:2,id:123&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;SecRule&lt;/span&gt; REQUEST_URI &lt;span class="s2"&gt;&amp;quot;.*&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;auditlog&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source : &lt;a class="reference external" href="https://www.technovelty.org/web/logging-post-requests-with-apache.html"&gt;https://www.technovelty.org/web/logging-post-requests-with-apache.html&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="apache"></category></entry><entry><title>Extract all base64 encoded images from a SVG</title><link href="//www.jujens.eu/posts/en/2017/Feb/13/extract-images-svg/" rel="alternate"></link><published>2017-02-13T00:00:00+01:00</published><updated>2017-02-13T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-02-13:/posts/en/2017/Feb/13/extract-images-svg/</id><summary type="html">&lt;p&gt;Recently, I had to integrate a SVG in an Aurelia template. Sadly, it contained a lot of images and they were all included in base64. It made the file almost unreadable with big blobs that prevented me to see the code and add the &amp;quot;proper Aurelia attributes&amp;quot; (eg &lt;tt class="docutils literal"&gt;if.bind …&lt;/tt&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently, I had to integrate a SVG in an Aurelia template. Sadly, it contained a lot of images and they were all included in base64. It made the file almost unreadable with big blobs that prevented me to see the code and add the &amp;quot;proper Aurelia attributes&amp;quot; (eg &lt;tt class="docutils literal"&gt;if.bind&lt;/tt&gt;). Hopefully, Python 3 is there to help!&lt;/p&gt;
&lt;p&gt;The script below takes as parameter the path to a SVG file and will extract all images encoded in base64 in separate files in the current folder. The SVG using these extracted images will be saved in the current folder with the name &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;svg-without-images.svg&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;base64&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;b64decode&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;&lt;span class="c1"&gt;# We define the proper XML namespaces to query the SVG.&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="n"&gt;NS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="s1"&gt;'svg'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'http://www.w3.org/2000/svg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;    &lt;span class="s1"&gt;'xlink'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'http://www.w3.org/1999/xlink'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_help&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./extract-images-svg.py SVG_FILE'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'This will extract the images included in b64 in the SVG.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_images_svg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="c1"&gt;# We open the file.&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;        &lt;span class="n"&gt;svg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;    &lt;span class="c1"&gt;# We find all images with xpath.&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;    &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;svg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.//svg:image'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;namespaces&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;NS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;        &lt;span class="c1"&gt;# We get the value of the image.&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;        &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{http://www.w3.org/1999/xlink}href'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;        &lt;span class="c1"&gt;# We check it is a base64 image. If so, we extract it.&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data:image/'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;            &lt;span class="c1"&gt;# We take the content of the image and its metadata&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;            &lt;span class="c1"&gt;# (only the format of the image is relevant to us).&lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;            &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_b64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;';base64,'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;            &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;            &lt;span class="c1"&gt;# Replace the base64 data by a link to an external image in the proper format.&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;            &lt;span class="n"&gt;img_file_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'img-&lt;/span&gt;&lt;span class="si"&gt;{index}&lt;/span&gt;&lt;span class="s1"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{format}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;img_format&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;            &lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{http://www.w3.org/1999/xlink}href'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_file_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;            &lt;span class="c1"&gt;# Save the extracted image.&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_file_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'wb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;img_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;                &lt;span class="n"&gt;img_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b64decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_b64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;    &lt;span class="c1"&gt;# Save the &amp;quot;corrected&amp;quot; SVG file.&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'svg-without-images.svg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;        &lt;span class="n"&gt;svg_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
&lt;span class="ln"&gt;45 &lt;/span&gt;                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;\
&lt;span class="ln"&gt;46 &lt;/span&gt;                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;        &lt;span class="n"&gt;svg_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svg_content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;
&lt;span class="ln"&gt;49 &lt;/span&gt;
&lt;span class="ln"&gt;50 &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;51 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;52 &lt;/span&gt;        &lt;span class="n"&gt;print_help&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt;53 &lt;/span&gt;        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;54 &lt;/span&gt;
&lt;span class="ln"&gt;55 &lt;/span&gt;    &lt;span class="n"&gt;extract_images_svg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Python"></category><category term="SVG"></category></entry><entry><title>Log POST data with apache</title><link href="//www.jujens.eu/posts/en/2017/Feb/13/log-post-requests-apache/" rel="alternate"></link><published>2017-02-13T00:00:00+01:00</published><updated>2017-02-13T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-02-13:/posts/en/2017/Feb/13/log-post-requests-apache/</id><summary type="html">&lt;p&gt;According to the manual, the easiest way to log the content of a POST request (for debugging purpose, in a production environment, it would increase the size of the logs and increase the probability to leak information) is to use the &lt;a class="reference external" href="https://httpd.apache.org/docs/2.4/fr/mod/mod_dumpio.html"&gt;dumpio module&lt;/a&gt;. For Apache 2.4, all you should …&lt;/p&gt;</summary><content type="html">&lt;p&gt;According to the manual, the easiest way to log the content of a POST request (for debugging purpose, in a production environment, it would increase the size of the logs and increase the probability to leak information) is to use the &lt;a class="reference external" href="https://httpd.apache.org/docs/2.4/fr/mod/mod_dumpio.html"&gt;dumpio module&lt;/a&gt;. For Apache 2.4, all you should do is:&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="c"&gt;# Put the logs in specific files to ease reading.&lt;/span&gt;
&lt;span class="nb"&gt;CustomLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/httpd/website.log&lt;/span&gt; combined
&lt;span class="nb"&gt;ErrorLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/httpd/website.error.log&lt;/span&gt;

&lt;span class="c"&gt;# Enable debug logging.&lt;/span&gt;
&lt;span class="nb"&gt;LogLevel&lt;/span&gt; &lt;span class="k"&gt;debug&lt;/span&gt;

&lt;span class="c"&gt;# Enable the module.&lt;/span&gt;
&lt;span class="nb"&gt;DumpIOInput&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;DumpIOOutput&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;LogLevel&lt;/span&gt; dumpio:trace7
&lt;/pre&gt;
&lt;p&gt;Sadly, I&amp;nbsp;never managed to make it work. Hopefully, there is another module which allows us to do that: &lt;tt class="docutils literal"&gt;mod_security&lt;/tt&gt;. You should configure it as follows:&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="c"&gt;# Enable the module.&lt;/span&gt;
&lt;span class="nb"&gt;SecRuleEngine&lt;/span&gt; &lt;span class="k"&gt;On&lt;/span&gt;
&lt;span class="nb"&gt;SecAuditEngine&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;

&lt;span class="c"&gt;# Setup logging in a dedicated file.&lt;/span&gt;
&lt;span class="nb"&gt;SecAuditLog&lt;/span&gt; &lt;span class="sx"&gt;/var/log/httpd/website-audit.log&lt;/span&gt;
&lt;span class="c"&gt;# Allow it to access requests body.&lt;/span&gt;
&lt;span class="nb"&gt;SecRequestBodyAccess&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;
&lt;span class="nb"&gt;SecAuditLogParts&lt;/span&gt; ABIFHZ

&lt;span class="c"&gt;# Setup default action.&lt;/span&gt;
&lt;span class="nb"&gt;SecDefaultAction&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;nolog,noauditlog,allow,phase:2&amp;quot;&lt;/span&gt;

&lt;span class="c"&gt;# Define the rule that will log the content of POST requests.&lt;/span&gt;
&lt;span class="nb"&gt;SecRule&lt;/span&gt; REQUEST_METHOD &lt;span class="s2"&gt;&amp;quot;^POST$&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;chain,allow,phase:2,id:123&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;SecRule&lt;/span&gt; REQUEST_URI &lt;span class="s2"&gt;&amp;quot;.*&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;auditlog&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://www.technovelty.org/web/logging-post-requests-with-apache.html"&gt;https://www.technovelty.org/web/logging-post-requests-with-apache.html&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="apache"></category></entry><entry><title>Form validation with Aurelia</title><link href="//www.jujens.eu/posts/en/2017/Jan/24/aurelia-validation/" rel="alternate"></link><published>2017-01-24T00:00:00+01:00</published><updated>2017-01-24T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-01-24:/posts/en/2017/Jan/24/aurelia-validation/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Update (2017-07-20):&lt;/strong&gt; &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-validation&lt;/span&gt;&lt;/tt&gt; now supports events, so it is much easier to disable the submission of the form until it is valid. See the &lt;a class="reference internal" href="#disable-the-submission-until-the-form-is-valid"&gt;Disable the submission until the form is valid&lt;/a&gt; section for the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update (2017-01-25):&lt;/strong&gt; after &lt;a class="reference external" href="https://gitter.im/aurelia/validation?at=5887be7fdcb66e4f76a70b0b"&gt;new exchanges&lt;/a&gt; with &lt;a class="reference external" href="https://github.com/dkent600"&gt;Doug Kent&lt;/a&gt; I was able to improve my …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Update (2017-07-20):&lt;/strong&gt; &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-validation&lt;/span&gt;&lt;/tt&gt; now supports events, so it is much easier to disable the submission of the form until it is valid. See the &lt;a class="reference internal" href="#disable-the-submission-until-the-form-is-valid"&gt;Disable the submission until the form is valid&lt;/a&gt; section for the code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update (2017-01-25):&lt;/strong&gt; after &lt;a class="reference external" href="https://gitter.im/aurelia/validation?at=5887be7fdcb66e4f76a70b0b"&gt;new exchanges&lt;/a&gt; with &lt;a class="reference external" href="https://github.com/dkent600"&gt;Doug Kent&lt;/a&gt; I was able to improve my workaround to disable the submission of the form until it is valid. See the &lt;a class="reference internal" href="#disable-the-submission-until-the-form-is-valid"&gt;Disable the submission until the form is valid&lt;/a&gt; section for the code.&lt;/p&gt;
&lt;p&gt;I promised &lt;a class="reference external" href="/posts/en/2016/Mar/15/ionic2-aurelia-f7/"&gt;some months ago&lt;/a&gt; that I will talk about form validation with &lt;a class="reference external" href="http://aurelia.io"&gt;Aurelia&lt;/a&gt;. At that time, the validation plugin was still under heavy development. Furthermore, aurelia-validation was dropped in favour of aurelia-validatejs and then aurelia-validatejs was dropped for aurelia-validation. Now things look to have settled down for &lt;a class="reference external" href="https://github.com/aurelia/validation"&gt;aurelia-validation&lt;/a&gt;. That's what I'll talk about today.&lt;/p&gt;
&lt;p&gt;From what I see in &lt;a class="reference external" href="http://aurelia.io/hub.html#/doc/article/aurelia/validation/latest/validation-basics"&gt;the documentation&lt;/a&gt;, the plugin is both powerful and expressive (many rules available, possibility to chain them, error reporting, possibility to create your own rules, possibility to hook on the render phase, …).&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#quick-overview" id="id1"&gt;Quick overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#more-advanced-example" id="id2"&gt;More advanced example&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#disable-the-submission-until-the-form-is-valid" id="id3"&gt;Disable the submission until the form is valid&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#workaround-1" id="id4"&gt;Workaround 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#workaround-2-looks-more-solid" id="id5"&gt;Workaround 2 (looks more solid)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#workaround-3-how-you-should-do-it" id="id6"&gt;Workaround 3 (how you should do it)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id7"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="quick-overview"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Quick overview&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To get started, you need to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Install aurelia-validation: &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;--save&lt;/span&gt; &lt;span class="pre"&gt;aurelia-validation&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Enable it in your application (in your &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt;):&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;standardConfiguration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-validation'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developmentLogging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The more direct way to use validation is to:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Import &lt;tt class="docutils literal"&gt;ValidationControllerFactory&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;ValidationRules&lt;/tt&gt; from &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-validation&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Inject &lt;tt class="docutils literal"&gt;ValidationControllerFactory&lt;/tt&gt; in you component &lt;tt class="docutils literal"&gt;&amp;#64;inject(ValidationControllerFactory)&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Create the validation controller: &lt;tt class="docutils literal"&gt;this.controller = &lt;span class="pre"&gt;controllerFactory.createForCurrentScope();&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Use &lt;tt class="docutils literal"&gt;ValidationRules&lt;/tt&gt; to create some validation rules. For instance to make a field named &lt;tt class="docutils literal"&gt;title&lt;/tt&gt; of the current class mandatory: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ValidationRules.ensure('title').required().on(this);&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In a nutshell, this JavaScript code:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-framework'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ValidationControllerFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ValidationRules&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-validation'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="err"&gt;&amp;#64;&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ValidationControllerFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createForCurrentScope&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;ValidationRules&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;with this template:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;title &amp;amp; validate&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You probably want to view the list of validation errors. To do that, you can use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;validation-errors&lt;/span&gt;&lt;/tt&gt; attribute like that:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;validation-errors&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;errors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;title &amp;amp; validate&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt; &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;controller.errors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;repeat&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;error of controller.errors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                ${error.message}
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This will display the default error message for each rule that failed. You can change this message with &lt;tt class="docutils literal"&gt;withMessage&lt;/tt&gt;: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ValidationRules.ensure('title').required().withMessage('Title&lt;/span&gt; must be provided in this &lt;span class="pre"&gt;form.').on(this)&lt;/span&gt;&lt;/tt&gt;. You can also use &lt;a class="reference external" href="https://github.com/aurelia/i18n"&gt;aurelia-i18n&lt;/a&gt; to translate these messages (see &lt;a class="reference external" href="http://aurelia.io/hub.html#/doc/article/aurelia/validation/latest/validation-basics/12"&gt;the documentation&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="more-advanced-example"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;More advanced example&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we've covered the basics, let's get back to my mobile todo application built with Aurelia and &lt;a class="reference external" href="http://framework7.io/"&gt;Framework7&lt;/a&gt;. I have a form to create a TODO that requires a title:&lt;/p&gt;
&lt;img alt="Page to view and edit todo" src="/images/ionic2-aurelia-f7/todo-view.png" style="width: 100%;" /&gt;
&lt;p&gt;My goal is to use aurelia-validation to:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Prevent the user to create a TODO until a title with at least 3 characters is supplied (just to see how we can chain rules for a property). In order to to that, I just need to use the proper validation rules (since the title is stored in a &lt;tt class="docutils literal"&gt;todo&lt;/tt&gt; property of my object, I don't use &lt;tt class="docutils literal"&gt;.on(this)&lt;/tt&gt; but &lt;tt class="docutils literal"&gt;.on(this.todo)&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;ValidationRules&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Title must at least be 3 chars long.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Display an error message next to the title with a proper error message. This message will of course be updated as the user types. To achieve that, I need to:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Change how validation is trigger: by default it is on blur (that is when the user leaves the field). Let's import &lt;tt class="docutils literal"&gt;validateTrigger&lt;/tt&gt; and update our controller: &lt;tt class="docutils literal"&gt;this.controller.validateTrigger = validateTrigger.changeOrBlur;&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Use the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;validation-errors&lt;/span&gt;&lt;/tt&gt; attribute on an element that only contains the input for my title. This way, the value bound to it will only contain errors for this field (by construction, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;validation-errors&lt;/span&gt;&lt;/tt&gt; contains errors only for the fields it contains):&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-inner&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;validation-errors&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;titleErrors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-title label&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Title
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt; &lt;span class="na"&gt;repeat&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;errorInfo of titleErrors&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;${errorInfo.error.message}&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-input&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- again since the title is in todo, I have to use todo.title, not just title --&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;todo.title &amp;amp; validate&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="section" id="disable-the-submission-until-the-form-is-valid"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Disable the submission until the form is valid&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At this point I ran into a problem: how can I disable the submission of a TODO until it is valid? If I use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;validation-errors.bind=&amp;quot;errors&amp;quot;&lt;/span&gt;&lt;/tt&gt; on an element that includes the full form, I can use &lt;tt class="docutils literal"&gt;errors.length === 0&lt;/tt&gt; to check that it is valid. The problem is, that when the page loads, the form is invalid but since validation hasn't run yet, the submit button will be active. If I validate the form in the &lt;tt class="docutils literal"&gt;attached&lt;/tt&gt; method of the component, &lt;tt class="docutils literal"&gt;errors&lt;/tt&gt; is not empty (so the button is correctly disabled) but the error message for the title is displayed too soon (before the user event interacted with the form which is not what I want).&lt;/p&gt;
&lt;p&gt;In Angular2, you can rely on the &lt;tt class="docutils literal"&gt;dirty&lt;/tt&gt; property of your form controller to know if the user has started to interact with the form. So I could use something like &lt;tt class="docutils literal"&gt;controller.dirty &amp;amp;&amp;amp; errors.length === 0&lt;/tt&gt; to enable/disable my button (see &lt;a class="reference external" href="https://medium.com/&amp;#64;daviddentoom/angular-2-form-validation-9b26f73fcb81"&gt;this article&lt;/a&gt; for form validation with Angular2).&lt;/p&gt;
&lt;del&gt;
Sadly there is no such property with aurelia-validation. There is &lt;a href="https://github.com/aurelia/validation/issues/318"&gt;an issue about this&lt;/a&gt; with a link to &lt;a href="http://www.sobell.net/aurelia-validation-events/"&gt;this blog post&lt;/a&gt; suggesting to hook on the rendering phase to solve this.
&lt;/del&gt;&lt;p&gt;There a way to easily do this with aurelia. See &lt;a class="reference internal" href="#workaround-3-how-you-should-do-it"&gt;Workaround 3 (how you should do it)&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="workaround-1"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id4"&gt;Workaround 1&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I asked on &lt;a class="reference external" href="https://gitter.im/aurelia/validation"&gt;gitter&lt;/a&gt; for help and &lt;a class="reference external" href="https://github.com/dkent600"&gt;Doug Kent&lt;/a&gt; suggested various &lt;a class="reference external" href="https://gitter.im/aurelia/validation?at=58878411c0de6f017fe67817"&gt;solutions&lt;/a&gt; the most promising being to use two controllers: one to validate the button, one to display the error. I didn't managed to get it to work but, based on this idea, I found a workaround (and I hope we will have a clean method to do this in the future):&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;I keep the controller as is for validation and error display.&lt;/li&gt;
&lt;li&gt;I use a &lt;tt class="docutils literal"&gt;Validator&lt;/tt&gt; to manually validate the form without impacting error reporting. The idea is to:&lt;ol class="arabic"&gt;
&lt;li&gt;Validate the form in &lt;tt class="docutils literal"&gt;attached&lt;/tt&gt;: this form can also be used to edit an existing todo (which has a valid title), so the save button can be enabled or disabled on page load. This validation is done with the &lt;tt class="docutils literal"&gt;Validator&lt;/tt&gt; which means no errors will be reported to the user.&lt;/li&gt;
&lt;li&gt;Watch on the &lt;tt class="docutils literal"&gt;title&lt;/tt&gt; property of my todo and validate the form each time it changes.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the relevant part of the code:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ObserverLocator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-framework'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ValidationControllerFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ValidationRules&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validateTrigger&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-validation'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="err"&gt;&amp;#64;&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ValidationControllerFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ObserverLocator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TodoPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// We rely on the controller to display the errors.
&lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createForCurrentScope&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// We rely on the validator to know if the canSave the todo or not
&lt;/span&gt;        &lt;span class="c1"&gt;// (update the canSave property in the validation method)
&lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="nx"&gt;ValidationRules&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Title must at least be 3 chars long.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateTrigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validateTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;changeOrBlur&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;attached&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;// results is an array of validation results. Each result has a
&lt;/span&gt;            &lt;span class="c1"&gt;// valid property set to true if the rule is valid.
&lt;/span&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I then use &lt;tt class="docutils literal"&gt;canSave&lt;/tt&gt; in my template:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;button button-big button-fill color-green ${canSave ? '' : 'disabled'}&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;saveTodo()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can view the full code &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/9978d01823d30a3c3d733add2c246fbe621bf022/aurelia-f7-todo/app/pages/todo/todo.js"&gt;here&lt;/a&gt; and &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/9978d01823d30a3c3d733add2c246fbe621bf022/aurelia-f7-todo/app/pages/todo/todo.html"&gt;here&lt;/a&gt;. It feels a bit hackish and I don't think this will scale to big forms.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="workaround-2-looks-more-solid"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id5"&gt;Workaround 2 (looks more solid)&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;After new exchanges &lt;a class="reference external" href="https://gitter.im/aurelia/validation?at=5887be7fdcb66e4f76a70b0b"&gt;on gitter&lt;/a&gt;, &lt;a class="reference external" href="https://github.com/dkent600"&gt;Doug Kent&lt;/a&gt; made another suggestion: use a custom validator instead of &lt;tt class="docutils literal"&gt;StandardValidator&lt;/tt&gt;. This way I should be able to hook on the validation phase and call a callback. Guess what: it worked. Let's see how.&lt;/p&gt;
&lt;p&gt;We start by creating an new class respecting the &lt;a class="reference external" href="https://github.com/aurelia/validation/blob/master/src/validator.ts"&gt;Validator interface&lt;/a&gt; and taking as argument an instance of the &lt;tt class="docutils literal"&gt;StandardValidator&lt;/tt&gt; which will do the actual validation work and a callback:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The idea is then to use the promise returned by &lt;tt class="docutils literal"&gt;this.validator.validateObject&lt;/tt&gt; to call our callback each time the promise is resolved:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;validateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We are almost done. We also need to trigger the validation when a property of the form is validated. For instance, here, when the user modifies the title of the todo, &lt;tt class="docutils literal"&gt;validateObject&lt;/tt&gt; won't be called. The controller will only call &lt;tt class="docutils literal"&gt;validateProperty&lt;/tt&gt;. That's not a big problem: once the property is validated, we can validate the whole form to update &lt;tt class="docutils literal"&gt;TodoPage.canSave&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;validateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Now let's see how we can use this. We initialize the validator and the controller in the constructor:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// validator is an instance of StandardValidator that was injected by DI.
&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;TodoValidator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateCanSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createForCurrentScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateTrigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validateTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;changeOrBlur&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Since this page can be used in two cases (creating a new todo and editing an existing one), we differ the creation of the validation rules a little bit: if we set them up in the constructor, they wouldn't apply on the proper object when editing a TODO. We wait for the activation and the page to distinguish between these to cases:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Creating a new TODO&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setupValidation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Editing a TODO&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Fetch the TODO.
&lt;/span&gt;    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Save the TODO in the current object.
&lt;/span&gt;    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Setup the validation rules.
&lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setupValidation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Launch validation to enable the save button if the edited TODO is valid.
&lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;setupValidation&lt;/tt&gt; method is just here to create our validation rules:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;ValidationRules&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;withMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Title must at least be 3 chars long.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;validate&lt;/tt&gt; method just calls &lt;tt class="docutils literal"&gt;this.validator.validateObject(this.todo);&lt;/tt&gt;. As for &lt;tt class="docutils literal"&gt;updateCanSave&lt;/tt&gt; it updates the &lt;tt class="docutils literal"&gt;canSave&lt;/tt&gt; property based on the results of the validation:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;updateCanSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validationResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;validationResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And that's it. The main advantage of this method, is that no matter how many fields you have, you don't need extra work. It can also easily be reused for different forms. You can see the full code &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/c5c28bf229071d8cb16d5fc7b13c3bfd4a384e64/aurelia-f7-todo/app/pages/todo/todo.js"&gt;here&lt;/a&gt; (with additional comments) and &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/c5c28bf229071d8cb16d5fc7b13c3bfd4a384e64/aurelia-f7-todo/app/pages/todo/todo.html"&gt;here&lt;/a&gt; (template).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="workaround-3-how-you-should-do-it"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id6"&gt;Workaround 3 (how you should do it)&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;As a follow up to &lt;a class="reference external" href="https://github.com/aurelia/validation/issues/318"&gt;this issue&lt;/a&gt; work has been done by Aurelia's contributor &lt;a class="reference external" href="https://github.com/jdanyow"&gt;Jeremy Danyow&lt;/a&gt; so we can execute a callback each time the validator is called. This greatly simplifies the code. You can view the documentation &lt;a class="reference external" href="https://github.com/aurelia/validation/blob/master/doc/article/en-US/validation-basics.md#events"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the constructor, we create the controller with a new validator and register the callback:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;controllerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createForCurrentScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateTrigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;validateTrigger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;changeOrBlur&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateWhole&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The callback passed to &lt;tt class="docutils literal"&gt;this.controller.subscribe&lt;/tt&gt; will be called each time the validator is run, for &lt;tt class="docutils literal"&gt;reset&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;validate&lt;/tt&gt; events. It has one parameter: the event. You can use it to filter by validation type or to get the errors associated with this run. Go &lt;a class="reference external" href="https://github.com/aurelia/validation/blob/master/src/validate-event.ts"&gt;here&lt;/a&gt; to view the full interface.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We don't need to manually run &lt;tt class="docutils literal"&gt;this.validateWhole&lt;/tt&gt; manually to initialize &lt;tt class="docutils literal"&gt;canSave&lt;/tt&gt; correctly. When the form is created and validation is bootstraped, the validator will run with a &lt;tt class="docutils literal"&gt;reset&lt;/tt&gt; event.&lt;/p&gt;
&lt;p&gt;In our case, we want to validate the whole form each time a field is validated so we can update our &lt;tt class="docutils literal"&gt;canSave&lt;/tt&gt; property:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;validateWhole&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canSave&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And we are done. This is much simplier and shorter that all the other workaround.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Running validation will not display errors messages associated to any field. So even if you validate multiple fields and display error messages for each one, &lt;tt class="docutils literal"&gt;validateWhole&lt;/tt&gt; will not have an impact.&lt;/p&gt;
&lt;p&gt;You can view the full file &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/master/aurelia-ux-todo/src/pages/edit.ts"&gt;here&lt;/a&gt; and the associated template &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/master/aurelia-ux-todo/src/pages/edit.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Conclusion&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You should now be able to validate your forms with Aurelia. If you have a question or a remark, please leave a comment.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="android"></category><category term="mobile"></category></entry><entry><title>Trouver tous les boutons sans attributs type</title><link href="//www.jujens.eu/posts/2017/Jan/16/trouver-boutons-sans-type/" rel="alternate"></link><published>2017-01-16T00:00:00+01:00</published><updated>2017-01-16T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-01-16:/posts/2017/Jan/16/trouver-boutons-sans-type/</id><summary type="html">&lt;p&gt;Certains navigateurs (comme Chrome) afficheront une erreur dans la console si vous avez des formulaires créés avec la balise &lt;tt class="docutils literal"&gt;form&lt;/tt&gt; et des boutons sans l'attribut &lt;tt class="docutils literal"&gt;type&lt;/tt&gt;. Il peut donc être intéressant d'avoir un petit script qui trouve tous ces boutons pour ajouter l'attribut &lt;tt class="docutils literal"&gt;type&lt;/tt&gt;. La bonne nouvelle c'est qu'avec Python …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Certains navigateurs (comme Chrome) afficheront une erreur dans la console si vous avez des formulaires créés avec la balise &lt;tt class="docutils literal"&gt;form&lt;/tt&gt; et des boutons sans l'attribut &lt;tt class="docutils literal"&gt;type&lt;/tt&gt;. Il peut donc être intéressant d'avoir un petit script qui trouve tous ces boutons pour ajouter l'attribut &lt;tt class="docutils literal"&gt;type&lt;/tt&gt;. La bonne nouvelle c'est qu'avec Python et &lt;a class="reference external" href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;BeautifulSoup 4&lt;/a&gt; c'est assez facile :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;html_file_path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'**/*.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recursive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note :&lt;/em&gt; Si vous utilisez Python 3.4 ou inférieur, remplacez &lt;tt class="docutils literal"&gt;import glob&lt;/tt&gt; par &lt;tt class="docutils literal"&gt;import glob2 as glob&lt;/tt&gt; et installez &lt;a class="reference external" href="https://pypi.python.org/pypi/glob2"&gt;glob2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On peut aussi légèrement modifier le script pour ajouter l'attribut avec la valeur par défaut &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;type=&amp;quot;button&amp;quot;&lt;/span&gt;&lt;/tt&gt; qui signale au navigateur que c'est un simple bouton qui ne doit rien faire vis à vis du formulaire (soumission ou remise à zéro). Le problème étant que cela peut casser le formatage du votre fichier.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;html_file_path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'**/*.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recursive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'button'&lt;/span&gt;

        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prettify&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="HTML"></category><category term="Python"></category><category term="formulaire"></category></entry><entry><title>Find all buttons without a type attribute</title><link href="//www.jujens.eu/posts/en/2017/Jan/16/trouver-boutons-sans-type/" rel="alternate"></link><published>2017-01-16T00:00:00+01:00</published><updated>2017-01-16T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2017-01-16:/posts/en/2017/Jan/16/trouver-boutons-sans-type/</id><summary type="html">&lt;p&gt;Some browsers (like Chrome) will display an error in the console if you have forms created with the &lt;tt class="docutils literal"&gt;form&lt;/tt&gt; tag and buttons without the &lt;tt class="docutils literal"&gt;type&lt;/tt&gt; attribute. So it can be useful to have a script that find all these buttons so you can add them the type attribute. The good …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Some browsers (like Chrome) will display an error in the console if you have forms created with the &lt;tt class="docutils literal"&gt;form&lt;/tt&gt; tag and buttons without the &lt;tt class="docutils literal"&gt;type&lt;/tt&gt; attribute. So it can be useful to have a script that find all these buttons so you can add them the type attribute. The good news is that with Python and &lt;a class="reference external" href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;BeautifulSoup 4&lt;/a&gt; it is really easy:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;html_file_path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'**/*.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recursive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; If you are using Python 3.4 or below, replace &lt;tt class="docutils literal"&gt;import glob&lt;/tt&gt; by &lt;tt class="docutils literal"&gt;import glob2 as glob&lt;/tt&gt; and install &lt;a class="reference external" href="https://pypi.python.org/pypi/glob2"&gt;glob2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is possible to slightly modify the script to add the type attribute with a default value like this &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;type=&amp;quot;button&amp;quot;&lt;/span&gt;&lt;/tt&gt;. This signals the browser that the buttons is not related to the form (submission or reset). The problem is: this may break the formating of you file.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;html_file_path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'**/*.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recursive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;number_buttons_without_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'button'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'button'&lt;/span&gt;

        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html_file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;html_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prettify&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fix_buttons_type&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="HTML"></category><category term="form"></category><category term="Python"></category></entry><entry><title>Make navigation user friendly on your Aurelia SPA</title><link href="//www.jujens.eu/posts/en/2016/Aug/28/navigation-user-friendly/" rel="alternate"></link><published>2016-08-28T00:00:00+02:00</published><updated>2016-08-28T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-08-28:/posts/en/2016/Aug/28/navigation-user-friendly/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#add-a-spinner" id="id1"&gt;Add a spinner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-the-wait-cursor-while-navigating" id="id2"&gt;Use the wait cursor while navigating&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#display-a-message-to-no-script-user" id="id3"&gt;Display a message to no-script user&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#more" id="id4"&gt;More&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="add-a-spinner"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Add a spinner&lt;/a&gt;&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Add the &lt;a class="reference external" href="http://fontawesome.io/"&gt;font awesome files&lt;/a&gt; to your project (CSS
and fonts files).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Import the font awesome style sheet in your &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/assets/fonts/fontawesome/font-awesome …&lt;/span&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#add-a-spinner" id="id1"&gt;Add a spinner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-the-wait-cursor-while-navigating" id="id2"&gt;Use the wait cursor while navigating&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#display-a-message-to-no-script-user" id="id3"&gt;Display a message to no-script user&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#more" id="id4"&gt;More&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="add-a-spinner"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Add a spinner&lt;/a&gt;&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Add the &lt;a class="reference external" href="http://fontawesome.io/"&gt;font awesome files&lt;/a&gt; to your project (CSS
and fonts files).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Import the font awesome style sheet in your &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;link&lt;/span&gt; &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/assets/fonts/fontawesome/font-awesome.min.css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Add the CSS code below to create the spinner either directly in the
&lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;style&lt;/tt&gt; tag or in a CSS file that you load in it:&lt;/p&gt;
&lt;pre class="code css literal-block"&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;splash&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="kt"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;splash&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;text-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Helvetica Neue&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Helvetica&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Arial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;splash&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;fa-spinner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;margin-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Update the &lt;tt class="docutils literal"&gt;div&lt;/tt&gt; in which your Aurelia application will be instantiated. Eg, replace:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="na"&gt;aurelia-app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;By:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="na"&gt;aurelia-app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;splash&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Arena of Titans&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fa fa-spinner fa-spin&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;i&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="use-the-wait-cursor-while-navigating"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Use the wait cursor while navigating&lt;/a&gt;&lt;/h2&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Change your &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;router-view&lt;/span&gt;&lt;/tt&gt; from:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;router-view&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;router-view&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;router-view&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;${router.isNavigating ? 'navigating' : ''}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;router-view&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;this will add a class &lt;tt class="docutils literal"&gt;navigating&lt;/tt&gt; to the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;router-view&lt;/span&gt;&lt;/tt&gt; tag when the
router is navigating and nothing otherwise.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Add this global CSS code to your application:&lt;/p&gt;
&lt;pre class="code css literal-block"&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;navigating&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;wait&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;navigating&lt;/span&gt; &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;wait&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This will display the wait cursor on the page and reduce the opacity on the
page to signal the user a navigation is going on. You can of course change
this code to match your application.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Don't forget to add the router to your object. In the
&lt;tt class="docutils literal"&gt;configureRouter(config, router)&lt;/tt&gt; function, do:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="display-a-message-to-no-script-user"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Display a message to no-script user&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some of your users may use an extension like &lt;a class="reference external" href="https://addons.mozilla.org/en-US/firefox/addon/noscript"&gt;noscript&lt;/a&gt; which disable
JavaScript on page you visit. By default, you will greet them with either a
blank page or a never-ending spinner. I think it is more user friendly to show
them a message asking to enable JavaScript. To do, add in your &lt;tt class="docutils literal"&gt;body&lt;/tt&gt; tag:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
 &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;noscript&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Arena of Titans cannot work without JavaScript. Please enable it.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Arena of Titans ne peut pas fonctionner sans JavaScript. Merci de l'activer.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;noscript&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="more"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;More&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To view the full details, look at these two commits:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/commits/a0630aadd969e87da85c9b87c972cb94d4443ae7"&gt;feat(index): improve feeling on page load&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/commits/e0ad0e16b804920442cd39749b4b964c64a98580"&gt;feat(app): notify visualy that the router is navigating&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="font awesome"></category></entry><entry><title>Switching an application to aurelia-cli</title><link href="//www.jujens.eu/posts/en/2016/Aug/17/switch-to-aurelia-cli/" rel="alternate"></link><published>2016-08-17T00:00:00+02:00</published><updated>2016-08-17T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-08-17:/posts/en/2016/Aug/17/switch-to-aurelia-cli/</id><summary type="html">&lt;p&gt;About a month ago, I started to make experiments with the &lt;a class="reference external" href="https://github.com/aurelia/webpack-plugin"&gt;webpack plugin for
Aurelia&lt;/a&gt; in order to split my
applications into multiple bundles. The application in question is a strategy
game called Arena of Titans. You can see it &lt;a class="reference external" href="http://www.arenaoftitans.com/"&gt;there&lt;/a&gt; (click play to create a game, or use &lt;a class="reference external" href="http://www.arenaoftitans.com/game/create"&gt;this …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;About a month ago, I started to make experiments with the &lt;a class="reference external" href="https://github.com/aurelia/webpack-plugin"&gt;webpack plugin for
Aurelia&lt;/a&gt; in order to split my
applications into multiple bundles. The application in question is a strategy
game called Arena of Titans. You can see it &lt;a class="reference external" href="http://www.arenaoftitans.com/"&gt;there&lt;/a&gt; (click play to create a game, or use &lt;a class="reference external" href="http://www.arenaoftitans.com/game/create"&gt;this
link&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;It was working well but the initial load of any page was slow. It was easy to
find out why: the bundle loaded by webpack was over 1.3 megabytes big. Why is it
that big? Well, it contained the game board which is about 1.1 megabytes
minified. Hence my will to split it into several bundles in order to speed up
the loading of the site. We still have to load the big board on the game page
but at least the site would work at an acceptable speed.&lt;/p&gt;
&lt;p&gt;I didn't manage to do it with webpack and after some time trying I thought what
about the new &lt;a class="reference external" href="https://github.com/aurelia/cli"&gt;aurelia-cli&lt;/a&gt;? I was able to do
it just fine. Here's how I did it. You can skip to the part about &lt;a class="reference internal" href="#bundles"&gt;bundles&lt;/a&gt; if
you're not interested in the rest.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#presentation-of-aurelia-cli" id="id1"&gt;Presentation of aurelia-cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#preparation" id="id2"&gt;Preparation&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#updates-in-main-js" id="id3"&gt;Updates in main.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#style" id="id4"&gt;Style&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#bundles" id="id5"&gt;Bundles&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#problems-encountered-with-bundles-and-their-solutions" id="id6"&gt;Problems encountered with bundles and their solutions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#tests" id="id7"&gt;Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id8"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="presentation-of-aurelia-cli"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Presentation of aurelia-cli&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://github.com/aurelia/cli"&gt;aurelia-cli&lt;/a&gt; is a project aimed to provide a
command line interface to create and run projects written with the &lt;a class="reference external" href="http://aurelia.io/"&gt;Aurelia
JavaScript framework&lt;/a&gt;. You can:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Create a new project with &lt;tt class="docutils literal"&gt;au new &lt;span class="pre"&gt;&amp;lt;project-name&amp;gt;&lt;/span&gt;&lt;/tt&gt;. You will then be guided
by an assistant to configure the project: standard ES6 or typescript, pure CSS
or SCSS/Less, …&lt;/li&gt;
&lt;li&gt;Run the project with &lt;tt class="docutils literal"&gt;au run&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;au run &lt;span class="pre"&gt;--watch&lt;/span&gt;&lt;/tt&gt; to rebuild the app when
you save a modification.&lt;/li&gt;
&lt;li&gt;Test the project with &lt;tt class="docutils literal"&gt;au test&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;au test &lt;span class="pre"&gt;--watch&lt;/span&gt;&lt;/tt&gt; to retest the app
when you save a modification.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It relies on &lt;a class="reference external" href="http://gulpjs.com/"&gt;gulp&lt;/a&gt; to launch its tasks and on
&lt;a class="reference external" href="https://www.browsersync.io/"&gt;Browsersync&lt;/a&gt; to provide a small HTTP server
that will reload you page when you do a modification.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="preparation"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Preparation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To avoid messing with the current code, I created a new aurelia-cli project in a
separate folder and I copied the proper files in my project:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The folder &lt;tt class="docutils literal"&gt;aurelia_project&lt;/tt&gt; which contains the gulp tasks required by
aurelia-cli to run and the configuration of the project.&lt;/li&gt;
&lt;li&gt;The &lt;tt class="docutils literal"&gt;scripts&lt;/tt&gt; folder which contains &lt;a class="reference external" href="http://requirejs.org"&gt;requirejs&lt;/a&gt; the
module loader used by project running with aurelia-cli and its text plugin to
load the HTML and CSS.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;test/aurelia-karma.js&lt;/span&gt;&lt;/tt&gt; a small file that allows you to use karma with
aurelia-cli projects. See the section about &lt;a class="reference internal" href="#tests"&gt;tests&lt;/a&gt; to learn more on that.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;karma.conf.js&lt;/tt&gt; so my karma configuration file doesn't rely on webpack any
more and meets the expectations of aurelia-cli.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I then updated my &lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt; file. To do that, I just compared my current
&lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt; with the one from the aurelia-cli project: I added the proper
dependencies (like aurelia-cli) and removed the old ones (like webpack).&lt;/p&gt;
&lt;p&gt;To avoid style warning with on the &lt;tt class="docutils literal"&gt;environement.js&lt;/tt&gt; file, I added it to the
&lt;tt class="docutils literal"&gt;.eslintignore&lt;/tt&gt;. This files contains utilities values to configure aurelia
(are we testing? are we in debug mode?):&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I then removed all of webpack configuration files and run &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-rf&lt;/span&gt; node_modules
&amp;amp;&amp;amp; npm install&lt;/tt&gt; to update the dependencies.&lt;/p&gt;
&lt;p&gt;Then, I adapted &lt;tt class="docutils literal"&gt;aurelia.json&lt;/tt&gt; to my needs:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The sources of my project are in a folder named &lt;tt class="docutils literal"&gt;app&lt;/tt&gt; and not in &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; as
it is by default. So I changed all paths (a replace &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; by &lt;tt class="docutils literal"&gt;app&lt;/tt&gt; did
it). I also had to correct &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-karma.js&lt;/span&gt;&lt;/tt&gt;. See the section about
&lt;a class="reference internal" href="#tests"&gt;tests&lt;/a&gt; to learn more about that.&lt;/li&gt;
&lt;li&gt;I configured the router to use push states. Which means my URLs look like
this: &lt;tt class="docutils literal"&gt;/game/create&lt;/tt&gt; and not like this &lt;tt class="docutils literal"&gt;#/game/create&lt;/tt&gt;. The problem is
that, by default, requirejs will load its bundle under
&lt;tt class="docutils literal"&gt;/game/scripts/bundle.js&lt;/tt&gt; instead of &lt;tt class="docutils literal"&gt;/scripts/bundle.js&lt;/tt&gt;. So I did my
first patch in aurelia-cli to &lt;a class="reference external" href="https://github.com/aurelia/cli/pull/243"&gt;add an option to use absolute path in requirejs&lt;/a&gt;. This way if you use
&lt;tt class="docutils literal"&gt;&amp;quot;useAbsolutePath&amp;quot;: true&lt;/tt&gt; in the &lt;tt class="docutils literal"&gt;build.targets&lt;/tt&gt; section of your
&lt;tt class="docutils literal"&gt;aurelia.json&lt;/tt&gt; file, your bundles will always be loaded in
&lt;tt class="docutils literal"&gt;/scripts/bundle.js&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also updated my &lt;tt class="docutils literal"&gt;global.scss&lt;/tt&gt; file to load fonts with an absolute URL and
&lt;tt class="docutils literal"&gt;aurelia_project/tasks/run.js&lt;/tt&gt; to change the port of Browsersync and disable
the &lt;a class="reference external" href="https://www.browsersync.io/docs/options#option-ghostMode"&gt;ghost mode&lt;/a&gt;
which mimics on all browsers the action you do in one: I want to be able to test
the game in different browsers running different players. I don't want it to
reproduce what I do in every browsers I have opened.&lt;/p&gt;
&lt;div class="section" id="updates-in-main-js"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Updates in main.js&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I reverted Aurelia's configuration function to the classical &lt;tt class="docutils literal"&gt;export function
configure(aurelia)&lt;/tt&gt; and I added the two lines below to enable development
logging only on debug mode and to enable the testing plugin when testing:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developmentLogging&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-testing'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I also updated my configuration of &lt;a class="reference external" href="https://www.npmjs.com/package/bluebird"&gt;bluebird.js&lt;/a&gt; a promise library for javascript in
&lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; from:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bluebird'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;longStackTraces&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;warnings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;longStackTraces&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;warnings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="style"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Style&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With webpack, you include the SCSS files like javascript but with the extension,
like this: &lt;tt class="docutils literal"&gt;import ./style/global.scss&lt;/tt&gt;. Webpack will then compile the file
and include it in the bundle thanks the loader you've configured. With
aurelia-cli, things are a little different. You include the file in your HTML
files like you require custom elements:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;require&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;./style/global.css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;require&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note that the extension of the file must be &lt;tt class="docutils literal"&gt;.css&lt;/tt&gt; whether you're using true
CSS or another language compiled to CSS like SCSS. The reason is that it will be
loaded as CSS. You just have to configure the &lt;tt class="docutils literal"&gt;cssPreprosessor&lt;/tt&gt; in your
&lt;tt class="docutils literal"&gt;aurelia.json&lt;/tt&gt; for the code to be correctly processed:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="s2"&gt;&amp;quot;cssProcessor&amp;quot;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;sass&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;displayName&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Sass&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;fileExtension&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;.scss&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;app/**/*.scss&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="bundles"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Bundles&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The ability to split my app into multiple bundles is the main reason I switched
to aurelia-cli. To create a bundle, all you have to do is to add an object with
a name and a list of dependencies to the &lt;tt class="docutils literal"&gt;build.bundles&lt;/tt&gt; array of your
&lt;tt class="docutils literal"&gt;aurelia.json&lt;/tt&gt; file.&lt;/p&gt;
&lt;p&gt;It works great but the first time I tried, my bundles were not filled
correctly. I tried to include files like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;quot;[site/**/*.js]&amp;quot;&lt;/span&gt;&lt;/tt&gt; but it
didn't work. I did some search and I found &lt;a class="reference external" href="https://github.com/aurelia/cli/issues/203#issuecomment-232845622"&gt;this comment&lt;/a&gt; by
&lt;a class="reference external" href="https://github.com/TylerJPresley"&gt;TylerJPresley&lt;/a&gt; on &lt;a class="reference external" href="https://github.com/aurelia/cli/issues/203"&gt;a issue about creating
multiple bundles with aurelia-cli&lt;/a&gt;
which gave me the solution: you have to put stars in front of the file
name. Like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;quot;[**/site/**/*.js]&amp;quot;&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;site-bundle.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/site/**/*.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;**/site/**/*.{css,html}&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;With that, my bundles were correctly created and filled but they were not
loaded. However, it turns out that I was missing some files in them: I did put
the site and game files but not &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;environment.js&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt;. As you might expect, without these files Aurelia could not work
correctly. So I create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;common-bundle.js&lt;/span&gt;&lt;/tt&gt; for them and other files needed in
the whole application:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;common-bundle.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/locale/**/*.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/app.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/environment.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/main.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/services/options.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/services/storage.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/services/browser-sniffer.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;[**/widgets/aot-options/*.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;**/app.html&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;**/widgets/aot-options/*.html&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;**/widgets/aot-options/*.css&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;&amp;quot;**/style/*.css&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In addition to bundling your app files, you can also include non Aurelia
dependencies from outside your project if they rely on &lt;a class="reference external" href="http://requirejs.org/docs/whyamd.html"&gt;AMD&lt;/a&gt;. For instance, here's how I define my
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;game-create-bundle.js&lt;/span&gt;&lt;/tt&gt; with &lt;a class="reference external" href="https://clipboardjs.com/"&gt;clipboardjs&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;game-create-bundle.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;clipboard&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;../node_modules/clipboard/dist&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;clipboard&amp;quot;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
       &lt;span class="s2"&gt;&amp;quot;[**/game/create/**/*.js]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s2"&gt;&amp;quot;**/game/create/**/*.{css,html}&amp;quot;&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can also prepend javascript files to a bundle. That's how requirejs and
bluebird are loaded. Here's the relevant excerpt from the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;vendor-bundle.js&lt;/span&gt;&lt;/tt&gt;
(defined &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/src/456d0578c1918bd9c7d9a3cd922f79ad99f1e49d/aurelia_project/aurelia.json?fileviewer=file-view-default#aurelia.json-148"&gt;here&lt;/a&gt;):&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="s2"&gt;&amp;quot;prepend&amp;quot;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="s2"&gt;&amp;quot;node_modules/bluebird/js/browser/bluebird.js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="s2"&gt;&amp;quot;scripts/require.js&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;At last but not least, some Aurelia modules contains multiple files that must be
resolved. To bundle those correctly, you need to use an object instead of the
name of the module in you &lt;tt class="docutils literal"&gt;dependencies&lt;/tt&gt; array. Like this:&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="s2"&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;aurelia-binding&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;i18next&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;path&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;../node_modules/i18next/dist/commonjs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;quot;main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;index&amp;quot;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can view the full definition of my &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;vendor-bundle.js&lt;/span&gt;&lt;/tt&gt; where this example
is taken &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/src/456d0578c1918bd9c7d9a3cd922f79ad99f1e49d/aurelia_project/aurelia.json?fileviewer=file-view-default#aurelia.json-148"&gt;here&lt;/a&gt;
and the definition of all my bundles &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/src/456d0578c1918bd9c7d9a3cd922f79ad99f1e49d/aurelia_project/aurelia.json?fileviewer=file-view-default#aurelia.json-83"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All in all, I think that bundling with aurelia-cli is very powerful, works well
and, once you know for the double stars, is quite easy to setup with the help of
a new project to give you the base configuration.&lt;/p&gt;
&lt;p&gt;In the end, I have 6 bundles for the application:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;vendor-bundle.js&lt;/span&gt;&lt;/tt&gt; with requirejs, &lt;a class="reference external" href="https://www.npmjs.com/package/bluebird"&gt;bluebird.js&lt;/a&gt; a promise library and all Aurelia
related files.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;common-bundle.js&lt;/span&gt;&lt;/tt&gt; that contains the translations, &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;environement.js&lt;/tt&gt; and various services and widgets common to the site and
the game.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;site-bundle.js&lt;/span&gt;&lt;/tt&gt; that contains all pages and widgets for the sites.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;game-common-bundle.js&lt;/span&gt;&lt;/tt&gt; that contains files required to create and play the
game.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;game-create-bundle.js&lt;/span&gt;&lt;/tt&gt; that contains all the widgets to create the game.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;game-play-bundle.js&lt;/span&gt;&lt;/tt&gt; that contains all you need to actually play the game.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="problems-encountered-with-bundles-and-their-solutions"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Problems encountered with bundles and their solutions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;aurelia-cli loads its bundles with &lt;a class="reference external" href="https://requirejs.org"&gt;requirejs&lt;/a&gt; which
I find great. Until during a test session a friend reported that he was not
redirected to the game page when he first tried to create a game. The second
time he tried everything worked fine.&lt;/p&gt;
&lt;p&gt;I dug into the problem and found out why it was failing. The bundle containing
the game is still big (about 1.3 megabytes). On some slow connection, it took
more than 7 seconds to load it. Which means that we encountered the default
timeout for requirejs and the app would consider the bundle could not be loaded
and thus didn't redirect the player to the page even after the script was
loaded. requirejs nicely logged an error with &lt;a class="reference external" href="http://requirejs.org/docs/errors.html#timeout"&gt;this link&lt;/a&gt; in the console.&lt;/p&gt;
&lt;p&gt;The solution is to use the &lt;tt class="docutils literal"&gt;waitSeconds&lt;/tt&gt; option of requirejs to increase the
value of the timeout (you can also disable it &lt;a class="reference external" href="http://requirejs.org/docs/api.html#config-waitSeconds"&gt;as the documentation&lt;/a&gt; says). I did some
tests directly in the generated bundle and it work.&lt;/p&gt;
&lt;p&gt;The problem is that at the time of this writing, aurelia-cli doesn't allow you
to give custom options to the loader. So, I made a &lt;a class="reference external" href="https://github.com/aurelia/cli/pull/282"&gt;pull request to allow the
user to do just that&lt;/a&gt; in order to
correctly solve my problem while still using the cli. I hope it will be merged
soon.&lt;/p&gt;
&lt;p&gt;In order to further improve load time on these slow connection, I preload the
big &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;game-play-bundle.js&lt;/span&gt;&lt;/tt&gt; with the board as soon as a user reaches the create
game page. To do that, I added the line below in the constructor of the create
game page:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'game/play/widgets/board/board'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You must use this syntax to load the script asynchronously. If you use:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'game/play/widgets/board/board'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;the script will be loaded synchronously which means the user can't prepare the
game until it is completely loaded. That is of course not my goal.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="tests"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Tests&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, since the code is not in the &lt;tt class="docutils literal"&gt;src&lt;/tt&gt; folder but in &lt;tt class="docutils literal"&gt;app&lt;/tt&gt;, I had to
correct &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-karma.js&lt;/span&gt;&lt;/tt&gt; (see &lt;a class="reference internal" href="#preparation"&gt;Preparation&lt;/a&gt; for where it comes from) the
file that boostrap karma for usage with aurelia-cli. I had to correct this line
(&lt;a class="reference external" href="https://github.com/aurelia/cli/blob/master/lib/resources/test/aurelia-karma.js#L52"&gt;52&lt;/a&gt;
at the time of this writing):&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;originalDefine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/base/src/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;into:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;originalDefine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/base/app/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I think it would be better for aurelia-karma to use &lt;tt class="docutils literal"&gt;paths.root&lt;/tt&gt; for
&lt;tt class="docutils literal"&gt;aurelia.json&lt;/tt&gt; (more general). I gave it a try but didn't succeed. But there
may be other ways to do this. See &lt;a class="reference external" href="https://github.com/aurelia/cli/issues/246"&gt;my issue on the subject for more details
paths.root from aurelia.json&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my test files, I had to change some import paths, remove my &lt;tt class="docutils literal"&gt;import
&lt;span class="pre"&gt;../setup&lt;/span&gt;&lt;/tt&gt; since it is automatically loaded by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-karma&lt;/span&gt;&lt;/tt&gt;. The
&lt;tt class="docutils literal"&gt;test/unit/setup.js&lt;/tt&gt; has the &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/src/9d3b2546251f532c4713a6e3f95db288a175dac8/test/unit/setup.js?at=master&amp;amp;fileviewer=file-view-default"&gt;same content as before&lt;/a&gt;
to import ployfills and initialize Aurelia:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-polyfills'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-pal-browser'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I also had to move my &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;test-utils.js&lt;/span&gt;&lt;/tt&gt; which contains various stubs I use in my
unit tests from the &lt;tt class="docutils literal"&gt;test/unit&lt;/tt&gt; folder into the &lt;tt class="docutils literal"&gt;app&lt;/tt&gt; folder so it is
correctly transpiled by babel. I also created a &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/src/456d0578c1918bd9c7d9a3cd922f79ad99f1e49d/aurelia_project/aurelia.json?fileviewer=file-view-default#aurelia.json-218"&gt;dedicated bundle&lt;/a&gt;
named &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;test-utils-bundle.js&lt;/span&gt;&lt;/tt&gt; to avoid loading it in the true application.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id8"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is it! Converting the project wasn't very hard but some problems (absolute
loading of bundles, some problems with testing and the inability to configure
requirejs) required some time to make it work correctly. Now I think that the
project is ready for the future of Aurelia tooling and I don't think I'll need
to switch tools again.&lt;/p&gt;
&lt;p&gt;If you want all the gory details, take a look at &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/commits/456d0578c1918bd9c7d9a3cd922f79ad99f1e49d"&gt;this merge commit&lt;/a&gt;
and the commits before it in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-cli&lt;/span&gt;&lt;/tt&gt; branch.&lt;/p&gt;
&lt;p&gt;Otherwise, you also take a look at my &lt;tt class="docutils literal"&gt;aurelia.json&lt;/tt&gt; file &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans/src/456d0578c1918bd9c7d9a3cd922f79ad99f1e49d/aurelia_project/aurelia.json?fileviewer=file-view-default"&gt;here&lt;/a&gt;,
browse the complete code of the app &lt;a class="reference external" href="https://bitbucket.org/arenaoftitans/arena-of-titans"&gt;there&lt;/a&gt; and see it in action
&lt;a class="reference external" href="http://www.arenaoftitans.com/"&gt;on the website&lt;/a&gt; (click play to create a game,
or use &lt;a class="reference external" href="http://www.arenaoftitans.com/game/create"&gt;this link&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you have a remark or question about this article or the game, leave a comment
below or contact me &lt;a class="reference external" href="https://twitter.com/jenselme_"&gt;on twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next step on my agenda, setup code coverage of the original sources of the app
(and not the bundle, that would be too easy). I hope I'll be able to make it
work and write about it soon. Stay tuned!&lt;/p&gt;
&lt;/div&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="aurelia-cli"></category></entry><entry><title>Utiliser des métaclasses pour créer simplement des enums en Python 3</title><link href="//www.jujens.eu/posts/2016/Aug/01/metaclasses-create-simple-enums-python3/" rel="alternate"></link><published>2016-08-01T00:00:00+02:00</published><updated>2016-08-01T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-08-01:/posts/2016/Aug/01/metaclasses-create-simple-enums-python3/</id><summary type="html">&lt;p&gt;Depuis la version 3.4, Python dispose d'une classe &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; qui permet de créer
des enums avec quelques propriétés intéressantes (itération, nombre d'éléments,
accès aux éléments de l'enum comme ceux d'un objet ou d'un dictionnaire). Je
vous laisse lire &lt;a class="reference external" href="https://docs.python.org/3/library/enum.html"&gt;la documentation&lt;/a&gt; pour les détails.&lt;/p&gt;
&lt;p&gt;Cependant, dans mon cas, je les …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Depuis la version 3.4, Python dispose d'une classe &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; qui permet de créer
des enums avec quelques propriétés intéressantes (itération, nombre d'éléments,
accès aux éléments de l'enum comme ceux d'un objet ou d'un dictionnaire). Je
vous laisse lire &lt;a class="reference external" href="https://docs.python.org/3/library/enum.html"&gt;la documentation&lt;/a&gt; pour les détails.&lt;/p&gt;
&lt;p&gt;Cependant, dans mon cas, je les utilise pour traquer certaines valeurs d'une
requête faites sur une application (par exemple : le nom de la requête envoyée
au serveur ou l'état d'un créneau – ouvert, fermé, pris). Les enum de base me
posent plusieurs problèmes&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Il faut entrer le nom et la valeur pour chaque membre, comme ceci&amp;nbsp;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlotState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OPEN'&lt;/span&gt;
    &lt;span class="n"&gt;CLOSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'CLOSED'&lt;/span&gt;
    &lt;span class="n"&gt;RESERVED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'RESERVED'&lt;/span&gt;
    &lt;span class="n"&gt;TAKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TAKEN'&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;J'oublie le &lt;tt class="docutils literal"&gt;.value&lt;/tt&gt; à chaque fois lorsque je fais un test entre la requête
et l'enum: je fais &lt;tt class="docutils literal"&gt;SlotState.OPEN == &lt;span class="pre"&gt;request['slot']['state']&lt;/span&gt;&lt;/tt&gt; au lieu de
&lt;tt class="docutils literal"&gt;SlotState.OPEN.value == &lt;span class="pre"&gt;request['slot']['state']&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Du coup, je me suis demandé si on ne pouvais pas faire plus simple pour mon
utilisation. Ce que j'aimerais c'est :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Utiliser le nom de l'attribut pour remplir automatiquement sa valeur.&lt;/li&gt;
&lt;li&gt;Tester directement avec l'attribut &lt;tt class="docutils literal"&gt;MonEnum.membre == 'VALEUR'&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Ne pas avoir à mettre manuellement en majuscule les propriétés, ie pouvoir
accéder aux éléments avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MonEnum['Valeur']&lt;/span&gt;&lt;/tt&gt; ou avec
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MonEnum['VALEUR']&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Garder les propriétés sympathiques des «&amp;nbsp;vrais&amp;nbsp;» enums Python :&lt;ul&gt;
&lt;li&gt;Longueur.&lt;/li&gt;
&lt;li&gt;Boucler sur tous les éléments de l'enum.&lt;/li&gt;
&lt;li&gt;Accès aux membres avec la notation crochet et comme aux attributs d'une
classe.&lt;/li&gt;
&lt;li&gt;Tester si un élément existe dans l'enum avec le mot clé &lt;tt class="docutils literal"&gt;in&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C'est possible en utilisant les métaclasses et en s'inspirant un peu de
&lt;tt class="docutils literal"&gt;EnumMeta&lt;/tt&gt; la métaclasse de la classe &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Qu'est-ce qu'une métaclasse ?  Pour faire simple, vous savez certainement qu'en
Python tout est objet et les classes ne font pas exception : ce sont des
instances d'une métaclasse. Cela nous permet donc de faire des opérations sur la
classe et non sur l'objet. Par exemple, si vous déclarer une méthode
&lt;tt class="docutils literal"&gt;__getitem__&lt;/tt&gt; dans une classe, vous pouvez utiliser sur l'instance comme ceci
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;instance['toto']&lt;/span&gt;&lt;/tt&gt; mais pas directement sur la classe comme cela
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MaClasse['toto']&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;C'est ce que permet de faire une métaclasse : vous déclarer la méthode
&lt;tt class="docutils literal"&gt;__getitem__&lt;/tt&gt; dans la métaclasse puis vous pouvez utiliser
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MaClasse['toto']&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Voici ma métaclasse &lt;tt class="docutils literal"&gt;SimpleEnumMeta&lt;/tt&gt; (voir les explications ci-dessous)&amp;nbsp;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleEnumMeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metacls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classdict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;         &lt;span class="n"&gt;object_attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt; &lt;span class="p"&gt;{})))&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;         &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metacls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classdict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;         &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classdict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;object_attrs&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;         &lt;span class="n"&gt;non_members&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;                 &lt;span class="n"&gt;non_members&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;             &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;                 &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;         &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;difference_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_members&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__iter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Concernant le fonctionnement de cette métaclasse :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Le constructeur &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt; (à ne pas confondre avec la méthode
d'initialisation &lt;tt class="docutils literal"&gt;__init__&lt;/tt&gt;) nous permet d'interagir avec la classe avant sa
&amp;quot;création&amp;quot; ce qui nous permet d'affecter des valeurs à nos attributs de
classe. Pour cela :&lt;ol class="arabic"&gt;
&lt;li&gt;On récupère les attributs communs à tous les objets pour pouvoir les
exclure de la liste des attributs dont on va affecter la valeur
automatiquement (ligne 3).&lt;/li&gt;
&lt;li&gt;On crée la classe grâce au constructeur de &lt;tt class="docutils literal"&gt;type&lt;/tt&gt;, la classe mère de
toutes les métaclasses (ligne 4).&lt;/li&gt;
&lt;li&gt;On stocke dans une propriété privée l'ensemble des attributs spécifiques à
notre enum (ligne 5). Cela nous permet de donner le nombre d'élément
contenu dans l'enum ainsi que de fournir un itérateur sur ces éléments
(méthodes &lt;tt class="docutils literal"&gt;__len__&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;__iter__&lt;/tt&gt;).&lt;/li&gt;
&lt;li&gt;Pour chaque attribut de l'enum, on affecte sa valeur comme le nom de
l'attribut (lignes 7 à 11).&lt;/li&gt;
&lt;li&gt;On supprime de la liste les attributs les éventuels attributs privés.&lt;/li&gt;
&lt;li&gt;Enfin, on renvoie la classe nouvellement créée (ligne 15).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Je pense que les autres méthodes parles d'elles mêmes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour l'utiliser, il suffit de créer une classe avec un argument
&lt;tt class="docutils literal"&gt;metaclass=SimpleEnumMeta&lt;/tt&gt; :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlotState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metaclass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SimpleEnumMeta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;CLOSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;RESERVED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;TAKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Vous devez assigner une valeur aux attributs puisque&amp;nbsp;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;test&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;n'est pas du Python valide et provoque une exception de type
&lt;tt class="docutils literal"&gt;NameError&lt;/tt&gt;. L'utilisation d'un tuple vide me semble un bon compromis pour
avoir du code valide et signaler que la valeur de l'attribut n'a pas
d'importance.&lt;/p&gt;
&lt;p&gt;On peut ensuite vérifier que l'on a bien les propriétés attendues :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;SlotState.OPEN == 'OPEN'&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SlotState['open']&lt;/span&gt; == 'OPEN'&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;len(SlotState) == 5&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;'OPEN' in SlotState&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;for state in SlotState: print(state)&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et voilà ! Si vous avez une question ou une remarque, n'hésiter pas à utiliser
les commentaires.&lt;/p&gt;
</content><category term="Programmation"></category><category term="Python"></category></entry><entry><title>Use metaclasses to create simple enums in Python 3</title><link href="//www.jujens.eu/posts/en/2016/Aug/01/metaclasses-create-simple-enums-python3/" rel="alternate"></link><published>2016-08-01T00:00:00+02:00</published><updated>2016-08-01T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-08-01:/posts/en/2016/Aug/01/metaclasses-create-simple-enums-python3/</id><summary type="html">&lt;p&gt;Since version 3.4, Python has an &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; class. It allows you to create enums
with some neat properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Iteration.&lt;/li&gt;
&lt;li&gt;Length.&lt;/li&gt;
&lt;li&gt;Access to the members with the &amp;quot;attribute&amp;quot; or &amp;quot;dict&amp;quot; notation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I leave you to &lt;a class="reference external" href="https://docs.python.org/3/library/enum.html"&gt;the documentation&lt;/a&gt; for the details.&lt;/p&gt;
&lt;p&gt;In my case, I am using them to track some …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Since version 3.4, Python has an &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; class. It allows you to create enums
with some neat properties:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Iteration.&lt;/li&gt;
&lt;li&gt;Length.&lt;/li&gt;
&lt;li&gt;Access to the members with the &amp;quot;attribute&amp;quot; or &amp;quot;dict&amp;quot; notation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I leave you to &lt;a class="reference external" href="https://docs.python.org/3/library/enum.html"&gt;the documentation&lt;/a&gt; for the details.&lt;/p&gt;
&lt;p&gt;In my case, I am using them to track some values of requests send to my
application (eg: the name of the request or the state of a slot – opened,
closed, taken). In this use case, I have some problem with the &amp;quot;standard&amp;quot; enums
as provided by the &lt;tt class="docutils literal"&gt;enum&lt;/tt&gt; package:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;I have to enter the name and value for each member which is kind of sad since
they are the same:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlotState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'OPEN'&lt;/span&gt;
    &lt;span class="n"&gt;CLOSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'CLOSED'&lt;/span&gt;
    &lt;span class="n"&gt;RESERVED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'RESERVED'&lt;/span&gt;
    &lt;span class="n"&gt;TAKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'TAKEN'&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;I always forget the &lt;tt class="docutils literal"&gt;.value&lt;/tt&gt; when I am testing: I do &lt;tt class="docutils literal"&gt;SlotState.OPEN ==
&lt;span class="pre"&gt;request['slot']['state']&lt;/span&gt;&lt;/tt&gt; instead of &lt;tt class="docutils literal"&gt;SlotState.OPEN.value ==
&lt;span class="pre"&gt;request['slot']['state']&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I asked myself: can I create my own enums that would solve these problems? I
want them to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Use the name of the attribute to fill its value.&lt;/li&gt;
&lt;li&gt;Test directly with the attribute: &lt;tt class="docutils literal"&gt;MonEnum.membre == 'VALEUR'&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Not to require to use caps in all access, ie access with either
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MonEnum['Valeur']&lt;/span&gt;&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MonEnum['VALEUR']&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Keep the neat properties of &amp;quot;true&amp;quot; Python enums:&lt;ul&gt;
&lt;li&gt;Length&lt;/li&gt;
&lt;li&gt;Loop over the elements&lt;/li&gt;
&lt;li&gt;Access to the elements with either the &amp;quot;attribute&amp;quot; or the dict notation.&lt;/li&gt;
&lt;li&gt;Test if an element is part of an enum with the &lt;tt class="docutils literal"&gt;in&lt;/tt&gt; keyword.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The answer is, it is possible with metaclasses and by getting some inspiration
from &lt;tt class="docutils literal"&gt;EnumMeta&lt;/tt&gt; the metaclass of the &lt;tt class="docutils literal"&gt;Enum&lt;/tt&gt; class.&lt;/p&gt;
&lt;p&gt;What is a metaclass? You probably know that in Python everything is an
object. Well, classes are no exceptions: they are instances of a metaclass. This
allows you to make operations on a class instead of an object. For instance, if
you declare a &lt;tt class="docutils literal"&gt;__getitem__&lt;/tt&gt; method on a class, you must use it on an instance
of the class like this &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;instance['toto']&lt;/span&gt;&lt;/tt&gt; but you cannot use it directly on
the class like this: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MyClass['toto']&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;However, you can do this with a metaclass: if you declare &lt;tt class="docutils literal"&gt;__getitem__&lt;/tt&gt; in the
metaclass of &lt;tt class="docutils literal"&gt;MyClass&lt;/tt&gt; you can use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;MyClass['toto']&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Here's my &lt;tt class="docutils literal"&gt;SimpleEnumMeta&lt;/tt&gt; metaclass (explanations below):&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleEnumMeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metacls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classdict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;         &lt;span class="n"&gt;object_attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,),&lt;/span&gt; &lt;span class="p"&gt;{})))&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;         &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metacls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classdict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;         &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classdict&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;object_attrs&lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;         &lt;span class="n"&gt;non_members&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;             &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;                 &lt;span class="n"&gt;non_members&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;             &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;                 &lt;span class="nb"&gt;setattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;         &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;difference_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;non_members&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;simple_enum_cls&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__iter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_member_names_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;How does it work?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The constructor &lt;tt class="docutils literal"&gt;__new__&lt;/tt&gt; (not to be mistaken with the initialization
function &lt;tt class="docutils literal"&gt;__init__&lt;/tt&gt;) allows us to interact with the class before its
&amp;quot;creation&amp;quot;. That allows us to affect values to the attribute of our class. To
do that:&lt;ol class="arabic"&gt;
&lt;li&gt;We get the set of attributes common to all objects in order to exclude them
from the set of attributes whose value we want to set automatically (line 3).&lt;/li&gt;
&lt;li&gt;We create the class thanks to the constructor of &lt;tt class="docutils literal"&gt;type&lt;/tt&gt; the super class
of all metaclasses (line 4).&lt;/li&gt;
&lt;li&gt;We store in a private property the set of attributes specific to our enum
(line 5). This allows us to give the correct number of elements of you enum
and to create an iterator to loop over them (methods &lt;tt class="docutils literal"&gt;__len__&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;__iter__&lt;/tt&gt;).&lt;/li&gt;
&lt;li&gt;For each attribute in the enum, we affect its value as the name of the
attribute (line 7 to 11).&lt;/li&gt;
&lt;li&gt;We then remove the private attributes from the list of the list of
attributes.&lt;/li&gt;
&lt;li&gt;In the end, we return the newly created class (ligne 15).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;I don't think I need to explain the other methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To use it, you just need to create a class with the &lt;tt class="docutils literal"&gt;metaclass=SimpleEnumMeta&lt;/tt&gt;
parameter:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlotState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metaclass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;SimpleEnumMeta&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;OPEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;CLOSED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;RESERVED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;TAKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You must assign a value to the attributes since:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;test&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;is not valid Python code and results in a &lt;tt class="docutils literal"&gt;NameError&lt;/tt&gt; exception. Using an
empty tuple looks like a good way to write valid code while signaling you don't
need to set the properties.&lt;/p&gt;
&lt;p&gt;You can then check that your class behave as intended:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;SlotState.OPEN == 'OPEN'&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;SlotState['open']&lt;/span&gt; == 'OPEN'&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;len(SlotState) == 5&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;'OPEN' in SlotState&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;for state in SlotState: print(state)&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Et voilà ! If you have a question, please leave a comment.&lt;/p&gt;
</content><category term="Programmation"></category><category term="Python"></category></entry><entry><title>Plugin for statistics with Piwik on an Aurelia SPA</title><link href="//www.jujens.eu/posts/en/2016/Jun/05/aurelia-piwik/" rel="alternate"></link><published>2016-06-05T00:00:00+02:00</published><updated>2016-06-05T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-06-05:/posts/en/2016/Jun/05/aurelia-piwik/</id><summary type="html">&lt;p&gt;On &lt;a class="reference external" href="http://www.arenaoftitans.com/"&gt;Arena of Titans&lt;/a&gt; a game based on the
&lt;a class="reference external" href="http://aurelia.io"&gt;Aurelia&lt;/a&gt; web framework I am developing with a friend, we
use &lt;a class="reference external" href="https://piwik.org"&gt;Piwik&lt;/a&gt; to have statistics about our visitors. When we
were about to launch the game, I realized that Piwik was not logging all the
pages but only the pages on …&lt;/p&gt;</summary><content type="html">&lt;p&gt;On &lt;a class="reference external" href="http://www.arenaoftitans.com/"&gt;Arena of Titans&lt;/a&gt; a game based on the
&lt;a class="reference external" href="http://aurelia.io"&gt;Aurelia&lt;/a&gt; web framework I am developing with a friend, we
use &lt;a class="reference external" href="https://piwik.org"&gt;Piwik&lt;/a&gt; to have statistics about our visitors. When we
were about to launch the game, I realized that Piwik was not logging all the
pages but only the pages on which you entered. It makes perfect sense:
navigation on the site is handled by Aurelia which means there is no page load
and if there is no page load, Piwik doesn't load the navigation.&lt;/p&gt;
&lt;p&gt;To go around this problem, I created a small plugin for Aurelia
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-piwik&lt;/span&gt;&lt;/tt&gt;. What it does is straightforward: it register a callback for
the &lt;tt class="docutils literal"&gt;router:navigation:success&lt;/tt&gt; event which is fired by Aurelia's router on
successful navigation. In this callback, I use Piwik's API to log the
navigation.&lt;/p&gt;
&lt;p&gt;You can easily use this plugin once installed by registering it in your
&lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;
 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;standardConfiguration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developmentLogging&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-piwik'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;I must say I am impressed by how easy it was to implement and use. After nearly
seven months of Aurelia usage, I am really glad to use this framework. If you
haven't checked it out yet, please do!&lt;/p&gt;
&lt;p&gt;The source are available under the MIT license &lt;a class="reference external" href="https://github.com/Jenselme/aurelia-piwik"&gt;on GitHub&lt;/a&gt;. The package is also available on
&lt;a class="reference external" href="https://www.npmjs.com/package/aurelia-piwik"&gt;npm&lt;/a&gt;.&lt;/p&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="Piwik"></category></entry><entry><title>Resolving blank page problem of Aurelia app with webpack on Safari</title><link href="//www.jujens.eu/posts/en/2016/Jun/03/safari-aurelia-i18n/" rel="alternate"></link><published>2016-06-03T00:00:00+02:00</published><updated>2016-06-03T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-06-03:/posts/en/2016/Jun/03/safari-aurelia-i18n/</id><summary type="html">&lt;p&gt;While asking users to test an Aurelia application, it appeared that it didn't
work on Safari due to this error:&lt;/p&gt;
&lt;img alt="Error in Safari console: Unhandled rejection webpackContextResolve" src="/images/safari-aurelia-i18n.png" /&gt;
&lt;p&gt;It comes from the fact that Safari doesn't support the internationalization
(window.Intl) API.&lt;/p&gt;
&lt;p&gt;In order to solve it, I had to manually include the &lt;a class="reference external" href="https://github.com/andyearnshaw/Intl.js/"&gt;Intl.js&lt;/a&gt;
polyfill. Since it …&lt;/p&gt;</summary><content type="html">&lt;p&gt;While asking users to test an Aurelia application, it appeared that it didn't
work on Safari due to this error:&lt;/p&gt;
&lt;img alt="Error in Safari console: Unhandled rejection webpackContextResolve" src="/images/safari-aurelia-i18n.png" /&gt;
&lt;p&gt;It comes from the fact that Safari doesn't support the internationalization
(window.Intl) API.&lt;/p&gt;
&lt;p&gt;In order to solve it, I had to manually include the &lt;a class="reference external" href="https://github.com/andyearnshaw/Intl.js/"&gt;Intl.js&lt;/a&gt;
polyfill. Since it is already pulled as a dependency, I just had to adapt the
bootstrap function of Aurelia with the setup code for Webpack of Intl.js:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Intl not present'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
             &lt;span class="s1"&gt;'intl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="s1"&gt;'intl/locale-data/jsonp/en.js'&lt;/span&gt;
         &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'intl'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'intl/locale-data/jsonp/en.js'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
             &lt;span class="nx"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;


 &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;standardConfiguration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;developmentLogging&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'aurelia-i18n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

             &lt;span class="c1"&gt;// register backend plugin
&lt;/span&gt;             &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;i18next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;XHR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

             &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;loadLocales&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                 &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                     &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                         &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;enTranslations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'200'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
                         &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                     &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                         &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frTranslations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'200'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
                         &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                     &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                         &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'404'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
                         &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                 &lt;span class="p"&gt;}&lt;/span&gt;
             &lt;span class="p"&gt;}&lt;/span&gt;

             &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                 &lt;span class="nx"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                     &lt;span class="nx"&gt;loadPath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'{{lng}}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="nx"&gt;ajax&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loadLocales&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="p"&gt;},&lt;/span&gt;
                 &lt;span class="nx"&gt;lng&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'t'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'i18n'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                 &lt;span class="nx"&gt;fallbackLng&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="p"&gt;});&lt;/span&gt;
         &lt;span class="p"&gt;});&lt;/span&gt;

     &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;aurelia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="aurelia-i18n"></category><category term="i18n"></category><category term="Intl"></category><category term="Safari"></category><category term="Webpack"></category></entry><entry><title>How I switched an Aurelia application to webpack</title><link href="//www.jujens.eu/posts/en/2016/Apr/24/switch-to-webpack/" rel="alternate"></link><published>2016-04-24T00:00:00+02:00</published><updated>2016-04-24T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-04-24:/posts/en/2016/Apr/24/switch-to-webpack/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I wrote this post when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-webpack&lt;/span&gt;&lt;/tt&gt; wast still in pre 1.0.0 release. As &lt;a class="reference external" href="http://www.jujens.eu/posts/en/2016/Apr/24/switch-to-webpack/#isso-74"&gt;niieani pointed out in the comments&lt;/a&gt; part of it may be outdated and you way want to use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-webpack&lt;/span&gt;&lt;/tt&gt; with &lt;a class="reference external" href="https://github.com/easy-webpack/core"&gt;easy-webpack&lt;/a&gt; instead. The general ideas are still valid though.&lt;/p&gt;
&lt;p&gt;First thing first: why would …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I wrote this post when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-webpack&lt;/span&gt;&lt;/tt&gt; wast still in pre 1.0.0 release. As &lt;a class="reference external" href="http://www.jujens.eu/posts/en/2016/Apr/24/switch-to-webpack/#isso-74"&gt;niieani pointed out in the comments&lt;/a&gt; part of it may be outdated and you way want to use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-webpack&lt;/span&gt;&lt;/tt&gt; with &lt;a class="reference external" href="https://github.com/easy-webpack/core"&gt;easy-webpack&lt;/a&gt; instead. The general ideas are still valid though.&lt;/p&gt;
&lt;p&gt;First thing first: why would I want to use &lt;a class="reference external" href="https://webpack.github.io/"&gt;webpack&lt;/a&gt; with &lt;a class="reference external" href="aurelia.io"&gt;Aurelia&lt;/a&gt; instead of the
default JSPM?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;I was tired of JSPM which I find buggy&lt;/li&gt;
&lt;li&gt;No need for gulp anymore&lt;/li&gt;
&lt;li&gt;All deps are in the &lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt; file and &lt;tt class="docutils literal"&gt;node_modules&lt;/tt&gt; folder&lt;/li&gt;
&lt;li&gt;webpack can build all kind of files (JS, TS, CSS, JSON, …) and perform
optimization on them&lt;/li&gt;
&lt;li&gt;Awesome dev server with hot reload.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are interested in the subject, you can read &lt;a class="reference external" href="http://ilikekillnerds.com/2016/03/ditching-jspmsystem-js-webpack/"&gt;this article from Dwayne
Charrington&lt;/a&gt; which
gives more details on why you may want to use webpack.&lt;/p&gt;
&lt;p&gt;Here are the steps I followed. I did them nearly a month back but haven't found
the time to write this article before today, so it is based on my small notes
and memories. I apologize if this article is not as precise as it could be. If
you have a specific question or run into trouble, please leave a
comment. Anyway, the thing to remember is that the migration went well and
webpack works very well with Aurelia.&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Update &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt;. Copy/Pasting the &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/index.html"&gt;index.html&lt;/a&gt;
from the skeleton with little adaptation should do the trick. You will also
need a &lt;tt class="docutils literal"&gt;index.prod.html&lt;/tt&gt; file for use in production. Again, &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/index.prod.html"&gt;the skeleton
has what you need&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Update dependencies in &lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt;. Adapt &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/package.json"&gt;the one from the skeleton&lt;/a&gt;. You
may need to add dependencies beside webpack specific ones (specified in the
skeleton) to get your app working. For instance, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;aurelia-logging-console&lt;/span&gt;&lt;/tt&gt;
was not explicitly in my &lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt; (not even under the &lt;tt class="docutils literal"&gt;jspm&lt;/tt&gt;
key). You can also get rid of the &lt;tt class="docutils literal"&gt;jspm&lt;/tt&gt; key. In my case, Aurelia will give
you a nice debug message if you are lacking a required dependency.&lt;/li&gt;
&lt;li&gt;Update configuration of Karma. See &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/karma.conf.js"&gt;karma.conf in the skeleton&lt;/a&gt;. For
your tests to work, you are very likely to need to bootstrap your tests by
adding to each file (you can also put that in a &lt;tt class="docutils literal"&gt;setup.js&lt;/tt&gt; file and import
it in your test files):&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="code js literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-pal-browser'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;ol class="arabic simple" start="4"&gt;
&lt;li&gt;Update &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; (create it if you don't have one). See &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/src/main.js"&gt;the skeleton for
inspiration&lt;/a&gt;. &lt;strong&gt;Important
note&lt;/strong&gt;: if you want you style files to be loaded with webpack, they must be
imported in a JS file. &lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; can be a good place to place these import.&lt;/li&gt;
&lt;li&gt;Copy &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/webpack.config.js"&gt;webpack.config.js&lt;/a&gt;
and &lt;a class="reference external" href="https://github.com/aurelia/skeleton-navigation/blob/master/skeleton-es2016-webpack/webpack.prod.config.js"&gt;webpack.prod.config.js&lt;/a&gt;
and adapt them if need be.&lt;/li&gt;
&lt;li&gt;Remove JSPM files: &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-rf&lt;/span&gt; jspm_packages config.js&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Remove unneeded node modules (eg jspm) &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-rf&lt;/span&gt; node_modules&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Remove gulp related files: &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-rf&lt;/span&gt; gulpfile.js build&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Install new dependencies: &lt;tt class="docutils literal"&gt;npm install&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Take care of submodules &lt;strong&gt;Not needed with aurelia-webpack 1.0.0&lt;/strong&gt;: if you see an error like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="literal-block"&gt;
.*$:106 Uncaught (in promise) Error: Cannot find module './aurelia-i18n/t'.
.*$:106 Uncaught (in promise) Error: Cannot find module './aurelia-i18n/nf'.
.*$:106 Uncaught (in promise) Error: Cannot find module './aurelia-i18n/df'.
Uncaught (in promise) Error: Cannot find module './aurelia-i18n/rt'.
&lt;/pre&gt;
&lt;p&gt;You need to enable sub-modules for this modules, with something like this:&lt;/p&gt;
&lt;pre class="code js literal-block"&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AureliaWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;includeSubModules&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;moduleId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aurelia-i18n&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;See the &lt;a class="reference external" href="https://github.com/aurelia/webpack-plugin/#configuration-options"&gt;documentation of the webpack plugin for more information&lt;/a&gt; on that.&lt;/p&gt;
&lt;p&gt;Normally you are ready to launch
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;./node_modules/.bin/webpack-dev-server&lt;/span&gt; &lt;span class="pre"&gt;--config&lt;/span&gt;
webpack.config.js &lt;span class="pre"&gt;--hot&lt;/span&gt; &lt;span class="pre"&gt;--inline&lt;/span&gt; &lt;span class="pre"&gt;--progress&lt;/span&gt; &lt;span class="pre"&gt;--devtool&lt;/span&gt; eval&lt;/tt&gt; and start
developing with Aurelia and webpack.&lt;/p&gt;
</content><category term="Aurelia"></category><category term="aurelia"></category><category term="webpack"></category></entry><entry><title>Small comparison of ionic2 and Aurelia + Framework7 for hybrid mobile applications</title><link href="//www.jujens.eu/posts/en/2016/Mar/15/ionic2-aurelia-f7/" rel="alternate"></link><published>2016-03-15T00:00:00+01:00</published><updated>2016-03-15T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2016-03-15:/posts/en/2016/Mar/15/ionic2-aurelia-f7/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Update (2017-08-14):&lt;/strong&gt; I finally published the part on Aurelia UX. See it &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Aug/14/aurelia-ux/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Updates (2017-01-24):&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;aurelia-interface has been deprecated in favour of &lt;a class="reference external" href="https://github.com/aurelia/ux"&gt;aurelia-ux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add a link to &lt;a class="reference external" href="/posts/en/2017/Jan/24/aurelia-validation/"&gt;my article&lt;/a&gt; about &lt;a class="reference external" href="http://aurelia.io/hub.html#/doc/article/aurelia/validation/latest/validation-basics"&gt;aurelia-validation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I don't think I'll start a project to use Aurelia with Framework7. I want to test aurelia-ux first. However …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Update (2017-08-14):&lt;/strong&gt; I finally published the part on Aurelia UX. See it &lt;a class="reference external" href="//www.jujens.eu/posts/en/2017/Aug/14/aurelia-ux/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Updates (2017-01-24):&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;aurelia-interface has been deprecated in favour of &lt;a class="reference external" href="https://github.com/aurelia/ux"&gt;aurelia-ux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add a link to &lt;a class="reference external" href="/posts/en/2017/Jan/24/aurelia-validation/"&gt;my article&lt;/a&gt; about &lt;a class="reference external" href="http://aurelia.io/hub.html#/doc/article/aurelia/validation/latest/validation-basics"&gt;aurelia-validation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I don't think I'll start a project to use Aurelia with Framework7. I want to test aurelia-ux first. However, someone is starting one: &lt;a class="reference external" href="https://github.com/alflennik/au7"&gt;https://github.com/alflennik/au7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#application-features" id="id1"&gt;Application features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#ionic2" id="id2"&gt;Ionic2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#aurelia-and-framework7" id="id3"&gt;Aurelia and Framework7&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#bonus" id="id4"&gt;Bonus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id5"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;I spent some time recently to develop a mobile application with the &lt;a class="reference external" href="http://ionicframework.com/"&gt;ionic
framework&lt;/a&gt;. This framework allows you to create
mobile applications for Android and iOS with HTML5 and CSS3 and &lt;a class="reference external" href="angularjs.org"&gt;AngularJS&lt;/a&gt;. Which means you can develop native like applications with
the ease of development of a web application: debug in a browser, use Javascript
and a framework you probably already know and that's it! No java or Swift, just
the power of the web. The application is then build for your phone with &lt;a class="reference external" href="https://cordova.apache.org"&gt;Apache
Cordova&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since they have a version 2 coming soon based on &lt;a class="reference external" href="https://angular.io/"&gt;Angular2&lt;/a&gt;, I decided to use directly this version (currently in
beta).&lt;/p&gt;
&lt;p&gt;However, on a another project, I use &lt;a class="reference external" href="aurelia.io"&gt;Aurelia&lt;/a&gt; a JavaScript
framework built with ES6 and around web standards aimed to create Single Page
Applications easily. And I must say I love it. It embraces ES6 and the new
possibilities offered by the language and its use of convention over
configuration makes it easy to work with.&lt;/p&gt;
&lt;p&gt;So I wanted to try to build a mobile application with it. There are plans for a
commercial addon called &lt;a class="reference external" href="https://github.com/joelcoxokc/aurelia-interface"&gt;Aurelia Interface&lt;/a&gt;. Sadly there is not much
information about it available apart from &lt;a class="reference external" href="https://vimeo.com/146402788"&gt;that video&lt;/a&gt;. After a small discussion on &lt;a class="reference external" href="https://gitter.im/Aurelia/Discuss"&gt;Aurelia's gitter&lt;/a&gt;, &lt;a class="reference external" href="https://gitter.im/Aurelia/Discuss?at=56e2cf603194fbd110962c9e"&gt;Scalpal suggested&lt;/a&gt; to look at
&lt;a class="reference external" href="http://framework7.io/"&gt;Framework7&lt;/a&gt; an HTML/CSS (with small bits of
JavaScript) framework to do pretty much the same thing as ionic without the
dependency on a particular framework. That's what I did and it turned out to
work well with Aurelia.&lt;/p&gt;
&lt;p&gt;Let's test!&lt;/p&gt;
&lt;div class="section" id="application-features"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Application features&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To compare the two possibilities, I wanted to do a basic todo list applications
that can:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;List all the saved todos (home page)&lt;/li&gt;
&lt;li&gt;Edit an existing todo&lt;/li&gt;
&lt;li&gt;Add a todo&lt;/li&gt;
&lt;li&gt;Mark a todo as done on the home page. Done todos must have their title
strike-through on the home page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All todos must be stored in the permanent SqlStorage of the phone.&lt;/p&gt;
&lt;p&gt;In additions to these features, both applications must work on a browser (for
debug and development purposes), on an android emulator and on an android phone.&lt;/p&gt;
&lt;p&gt;Here is how the home page looks like (Aurelia + Framework7 on the left, Ionic2 +
Angular2 on the right):&lt;/p&gt;
&lt;img alt="main page of the application" src="/images/ionic2-aurelia-f7/todos-list.png" style="width: 100%;" /&gt;
&lt;p&gt;And the todo page (Aurelia + Framework7 on the left, Ionic2 + Angular2 on the
right):&lt;/p&gt;
&lt;img alt="Page to view and edit todo" src="/images/ionic2-aurelia-f7/todo-view.png" style="width: 100%;" /&gt;
&lt;p&gt;The complete code of the applications is available &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7"&gt;on github&lt;/a&gt; under the
MIT license. Normally, the READMEs are complete enough to let you try the
applications. If you encounter any problem, leave a comment or open an issue!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="ionic2"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Ionic2&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I wrote this version in &lt;a class="reference external" href="http://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt; a
language made by Microsoft to ease the development of huge frontend applications
and not ES6 since it is the recommended way for Angular2 applications (Angular2
is itself written in TypeScript).&lt;/p&gt;
&lt;p&gt;To organize the application, I followed the standard structure proposed by
ionic:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;An &lt;tt class="docutils literal"&gt;app&lt;/tt&gt; folder with the code. In this app folder:&lt;ul&gt;
&lt;li&gt;each pages (JS, HTML and eventually SASS) are grouped in a folder within
&lt;tt class="docutils literal"&gt;pages&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Global theme SASS files are in the &lt;tt class="docutils literal"&gt;theme&lt;/tt&gt; folder.&lt;/li&gt;
&lt;li&gt;Boostrap (app.ts) and utils (models.ts) are directly in &lt;tt class="docutils literal"&gt;app&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;tt class="docutils literal"&gt;build&lt;/tt&gt; folder used for debugging and by Cordova to generate the final
application. It contains the &lt;tt class="docutils literal"&gt;index.html&lt;/tt&gt; generated by ionic and will
contain all the built files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, let's talk of &lt;tt class="docutils literal"&gt;models.ts&lt;/tt&gt;. It only contains one class and is used in
the application as a type for the TypeScript compiler (and completion).&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In &lt;tt class="docutils literal"&gt;app.ts&lt;/tt&gt; the application is bootstrapped. It is generated by ionic. I only
changed the value of &lt;tt class="docutils literal"&gt;MyApp#rootPage&lt;/tt&gt; so its value is &lt;tt class="docutils literal"&gt;ListTodosPage&lt;/tt&gt; the
JavaScript class that defines my root page.&lt;/p&gt;
&lt;p&gt;That leads us to the first important concept of Ionic2: navigation doesn't work
with URLs. As you'll see if you launch the app, the URL is never updated. To
navigate between pages, you use a &lt;tt class="docutils literal"&gt;NavController&lt;/tt&gt; object and pass the page on
which you want to go, like that:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TodoPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;A page being a class decorated with &lt;tt class="docutils literal"&gt;&amp;#64;Page&lt;/tt&gt; a decorator that comes from the
ionic framework.&lt;/p&gt;
&lt;p&gt;On the main page, we display the navbar and the list of all todos. To do that,
you use in your template the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ion-navbar&lt;/span&gt;&lt;/tt&gt; element. This allows you to easily
customize the navbar for each page. Ionic will also automatically add a &lt;em&gt;Back&lt;/em&gt;
button in this navbar when you navigate to another page.&lt;/p&gt;
&lt;p&gt;The main content of the page must be inside the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ion-content&lt;/span&gt;&lt;/tt&gt; element. Almost
all the elements you will put in it are defined by ionic to help you and starts
with &lt;em&gt;ion&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You can also add Angular2 markup:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;if the tag starts by a star (*), it's a template, like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;*ngFor=&amp;quot;#todo&lt;/span&gt; of
todos, #index = index&amp;quot;&lt;/tt&gt;. Note that the syntax is particular: to create a
variable in a template, you must put a pound sing (#) before the name of the
variable.&lt;/li&gt;
&lt;li&gt;if the tag is between parenthesis it is bound to an event like
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;(click)=&amp;quot;viewTodo(todo)&amp;quot;&lt;/span&gt;&lt;/tt&gt;. The value of the tag will be executed when the
event occurs.&lt;/li&gt;
&lt;li&gt;if the tag is between bracket like &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;[class]=&amp;quot;getClass(todo)&amp;quot;&lt;/span&gt;&lt;/tt&gt; it means its
value is one way bound to the expression you pass.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-navbar&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;navbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;TODO list&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-navbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-content&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-list&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngFor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#todo of todos, #index = index&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;todo&lt;/span&gt;&lt;span class="err"&gt;)&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;viewTodo&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="err"&gt;)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;{{ todo.title }}&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;item-right&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;markTodoDone&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;todo&lt;/span&gt;&lt;span class="err"&gt;)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Toggle done&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-list&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;full&lt;/span&gt; &lt;span class="na"&gt;round&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;addTodo&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-content&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On the TypeScript side, we have a class &lt;tt class="docutils literal"&gt;ListTodosPage&lt;/tt&gt; decorated by
&lt;tt class="docutils literal"&gt;&amp;#64;Page&lt;/tt&gt;. This decorator is only used here to defined the template used for the
page but it is also used to define which pipes (filters in Angular2 terminology)
and directives are available in the template.&lt;/p&gt;
&lt;p&gt;In the constructor, we create the SQL database if it doesn't exist and retrieve
the todos:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'CREATE TABLE IF NOT EXISTS todos(id integer primary key unique, title VARCHAR(10), description TEXT, done BOOLEAN)'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SELECT * FROM todos'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To view a particular todo, we use the navigation controller with navigation
parameters:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TodoPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To add a todo, we just omit the navigation parameter.&lt;/p&gt;
&lt;p&gt;We can then retrieve the todo on the &lt;tt class="docutils literal"&gt;TodoPage&lt;/tt&gt; like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;navParams&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NavParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;navParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;navParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Once we have our todo (the one we want to edit or a new one), we can create the
form and bind its default value to the existing todo. This way, if we have an
existing todo, the from will be prefilled with the correct values.&lt;/p&gt;
&lt;p&gt;I must say that forms in Angular2 are a huge beast and I am not sure to fully
see the interest of such a complex system (at least in most cases). The
programming API and the template tags are powerful and allow you to create fine
grained validators to suit your needs but they are hard to understand at
first. You have a simple syntax which suffers from lack of functionality and a
powerful and verbose one (which I use here). Let's look at the code:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compose&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;Validators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;])),&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Control&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todoForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ControlGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todoForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todoForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todoForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'done'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;First we defined the group of input we want. We give them a default value and
eventually the validator use to determine if the value is correct or not. Then
we create the form and extract from it the controls that will be used in the
template for validation.&lt;/p&gt;
&lt;p&gt;Now we can look at the template. I won't dig into it. If you want to learn more
about forms in Angular2, visit &lt;a class="reference external" href="http://learnangular2.com/forms/"&gt;this page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Just see how we use the controls to see if a field is correct or not and note
that we use the &lt;tt class="docutils literal"&gt;[ngFormModel]&lt;/tt&gt; tag to bind the form to the proper form
object.&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;ngFormModel&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;todoForm&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ngSubmit&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;todoForm&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;!&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;touched&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt; &lt;span class="na"&gt;floating&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;ngFormControl&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-input&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="na"&gt;ngIf&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;title.hasError('required') &amp;amp;&amp;amp; title.touched&amp;quot;&lt;/span&gt;
         &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;error-box&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
             * Title is required!
     &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;!&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;touched&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt; &lt;span class="na"&gt;floating&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Description&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-textarea&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;ngFormControl&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-textarea&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;!&lt;/span&gt;&lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt; &lt;span class="err"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;touched&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Done&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ion-checkbox&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;ngFormControl&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-checkbox&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ion-item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;full&lt;/span&gt; &lt;span class="na"&gt;round&lt;/span&gt; &lt;span class="na"&gt;danger&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;reset&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;)=&amp;quot;&lt;/span&gt;&lt;span class="na"&gt;cancel&lt;/span&gt;&lt;span class="err"&gt;()&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Cancel&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;full&lt;/span&gt; &lt;span class="na"&gt;round&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="err"&gt;]=&amp;quot;!&lt;/span&gt;&lt;span class="na"&gt;todoForm&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valid&lt;/span&gt;&lt;span class="err"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Save&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We can then save the todo with an SQL query and parameters replacement:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'UPDATE todos SET title = ?, description = ?, done = ? WHERE id = ?'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;todoValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todoValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;todoValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="aurelia-and-framework7"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Aurelia and Framework7&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I decided to use &lt;a class="reference external" href="https://webpack.github.io/"&gt;webpack&lt;/a&gt; (an official skeleton
is &lt;a class="reference external" href="http://blog.durandal.io/2016/03/10/aurelia-loves-webpack/"&gt;available&lt;/a&gt;)
instead of the default SystemJS. Two reasons for that:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;It's a good way to test webpack support&lt;/li&gt;
&lt;li&gt;During my initial research I found that people had problems with SystemJS and
cordova. Since webpack is used by ionic2, I expected it to work well.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I followed the same structure than for ionic: each pages in
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;app/pages/&amp;lt;pagename&amp;gt;&lt;/span&gt;&lt;/tt&gt;, services in &lt;tt class="docutils literal"&gt;app/services&lt;/tt&gt; and bootstrap (&lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt;
and &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt; directly in the app folder.&lt;/p&gt;
&lt;p&gt;The HTML code in index.html and app.html is almost a copy/paste from the getting
started of Framework7. There is just one point in app.html that is different: in
the getting started, the code is design for iOS. To use the material design
stylesheet (like I did), replace &lt;tt class="docutils literal"&gt;&amp;lt;div &lt;span class="pre"&gt;class=&amp;quot;pages&lt;/span&gt; &lt;span class="pre"&gt;navbar-through&lt;/span&gt;
&lt;span class="pre"&gt;toolbar-through&amp;quot;&amp;gt;&lt;/span&gt;&lt;/tt&gt; by &lt;tt class="docutils literal"&gt;&amp;lt;div &lt;span class="pre"&gt;class=&amp;quot;pages&lt;/span&gt; &lt;span class="pre"&gt;navbar-fixed&lt;/span&gt;
&lt;span class="pre"&gt;toolbar-through&amp;quot;&amp;gt;&lt;/span&gt;&lt;/tt&gt;. Otherwise, the content of the page will partially be in the
navbar (due to a missing &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;padding-top:&lt;/span&gt; 46px&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;main.js&lt;/tt&gt; contains nothing particular, it's just the standard main provided by
the skeleton.&lt;/p&gt;
&lt;p&gt;Since navigation in the app will rely on the Aurelia router, we have to defines
our route in &lt;tt class="docutils literal"&gt;app.js&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;configureRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Aurelia'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
             &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="nx"&gt;moduleId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'pages/list-todos/list-todos'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'todos'&lt;/span&gt;
         &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'todo/:id'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
             &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="nx"&gt;moduleId&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'pages/todo/todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="nx"&gt;nav&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'View Todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;]);&lt;/span&gt;

     &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And to navigate, I use either:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigateToRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To view/edit a precise todo. This allows me to get the todo with the given id
from storage. To add a new todo, I use:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/todo'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To navigate to the route without the parameter.&lt;/p&gt;
&lt;p&gt;Concerning the templates, nothing fancy. Just think to put your code in a div
with either the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;list-block&lt;/span&gt;&lt;/tt&gt; or the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;content-block&lt;/span&gt;&lt;/tt&gt; class depending on what
you want to do:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-content&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;repeat&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;todo of todos&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;viewTodo(todo)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-inner ${todo.done === true || todo.done === 'true' ? 'done' : ''}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
           ${todo.title}
       &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
       &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;button button-fill&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;toggleDone(todo)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Toggle Done&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We use Aurelia's binding mechanism to make the link with the JavaScript:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;We repeat the element with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;repeat.for=&amp;quot;todo&lt;/span&gt; of todos&amp;quot;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Bind a click event to a function with &lt;tt class="docutils literal"&gt;click.delegate&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Use string interpolation to display the values with &lt;tt class="docutils literal"&gt;${todo.title}&lt;/tt&gt; or to
update the value of a tag with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;class=&amp;quot;item-inner&lt;/span&gt; ${todo.done === true ||
todo.done === 'true' ? 'done' : &lt;span class="pre"&gt;''}&amp;quot;&lt;/span&gt;&lt;/tt&gt;. The part from &lt;tt class="docutils literal"&gt;${&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;}&lt;/tt&gt; will be
replaced by the value of the expression computed by Aurelia.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main difference with the ionic app is that I used &lt;a class="reference external" href="https://github.com/localForage/localForage"&gt;localForage&lt;/a&gt; in a custom class to store the
todos. localForage is a small library by Mozilla that uses localStorage if neither IndexedDB nor WebSQL is supported with an API close the localStorage. With ionic, you have a simple way to use SQLite on the phone and
WebSQL on your browser with nice capabilities for SQL queries but that's a ionic
thing. Since behind the scenes, it relies on Cordova, it should be possible to
use it with Aurelia and Framework7 but it felt overkill for my small test.&lt;/p&gt;
&lt;p&gt;On the page to edit todos, nothing fancy. I create a nice looking form with the
good classes. The structure is a little bit complicated but is necessary to have
the proper theme. The rest is just classic html (here the code for one field):&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-inner&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-title label&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;item-input&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Title&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;todo.title&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Just note that in forms, Aurelia will do two way data bindings with
&lt;tt class="docutils literal"&gt;value.bind&lt;/tt&gt; whereas everywhere else it will do one way data bindings by
default for performance reasons.&lt;/p&gt;
&lt;p&gt;In the JavaScript, we just have to load the proper todo:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To allow the todo to be saved, I do a basic check on the title (it must not be
empty). No message saying that the field is required if the user touches it is displayed. That's the
other import difference with ionic. It is due to a bug in &lt;a class="reference external" href="https://github.com/aurelia/validation/issues/226"&gt;aurelia-validation&lt;/a&gt; about how translations are
loaded with webpack. This is clearly behind what I did in ionic but I'll update
the code and this article once it is fixed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I created a new post about validation and Aurelia. The code samples used in it are based on this application You can see it &lt;a class="reference external" href="/posts/en/2017/Jan/24/aurelia-validation/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;get&lt;/span&gt; &lt;span class="nx"&gt;canSave&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="section" id="bonus"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Bonus&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It's not useful for my application, but I wanted to show how to use Framework7's
JavaScript should you need it. In a javascript file (you can name it &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/master/aurelia-f7-todo/app/services/f7.js"&gt;f7.js&lt;/a&gt;)
put the code below:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="c1"&gt;// Load JS for webpack
&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="s1"&gt;'framework7'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="c1"&gt;// Create F7 object
&lt;/span&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;F7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Framework7&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;material&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can then use it as you would expect:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;F7&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'f7'&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;'aurelia-framework'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;&amp;#64;&lt;/span&gt;&lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;F7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ListTodosPage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;f7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;f7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And in your HTML:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;click&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;f7.openPanel('left')&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;button button-big button-fill&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Open Left Panel&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To see a usage, go &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/master/aurelia-f7-todo/app/pages/list-todos/list-todos.js"&gt;here&lt;/a&gt;
for my code and &lt;a class="reference external" href="https://github.com/Jenselme/tests-ionic2-and-aurelia-framework7/blob/master/aurelia-f7-todo/app/pages/list-todos/list-todos.html"&gt;there&lt;/a&gt;
for the associated template.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Both application have roughly the same amount of code: 164 lines of JS and 40
lines of HTML for ionic and 143 lines of JS and 103 lines of HTML for
Aurelia/Framework7. Since my storage service is about 40 lines that are
handled by directly by ionic, I have about 100 lines of JS code for
Aurelia. There is more HTML but it's mostly the bootstrap required for
Framework7.&lt;/li&gt;
&lt;li&gt;I find Aurelia lighter and easier to use. Even if typescript has some nice
features like type error detection and a better auto-completion (since it can
be based on the type of the object), it looks Javaish with type declarations
and interfaces. In addition to that, the syntax for the template is weird (and
it breaks some HTML validators like the one integrated in NetBeans IDE). I've
used it for some days now, so I begin to get use to it but with my fist
experience with Aurelia I didn't have this incomfortable moments at first:
templating is plain and simple &lt;tt class="docutils literal"&gt;tag.bind&lt;/tt&gt; (default) or &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tag.two-way&lt;/span&gt;&lt;/tt&gt; or
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tag.one-way&lt;/span&gt;&lt;/tt&gt; depending on what you want to do, string interpolation works
everywhere and is just plain ES6 template strings.&lt;/li&gt;
&lt;li&gt;ionic uses a lot of custom elements and tags. I guess the goal is to make the
code less verbose, but sometime it is confusing. For instance, to make a text
input field, you use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;lt;ion-input&lt;/span&gt; &lt;span class="pre"&gt;type=&amp;quot;text&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/tt&gt;. So logically to make a
checkbox, I tried &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;lt;ion-input&lt;/span&gt; &lt;span class="pre"&gt;type=&amp;quot;checkbox&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/tt&gt; (which doesn't work)
instead of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;&amp;lt;ion-checkbox&lt;/span&gt; &lt;span class="pre"&gt;[ngFormControl]=&amp;quot;done&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/tt&gt;. On the
contrary, Framework7 is just plain HTML. You just have to respect a certain
structure (well detailed on the documentation) and put the proper classes on
your element. So it can integrate with pretty much everything and it's quite
easy to learn.&lt;/li&gt;
&lt;li&gt;ionic has some good bindings with Corodova. For instance its ability to use
WebSQL on your browser but SQLite on your phone. There's no easy way (yet?) to
do that with Aurelia/Framework7. Maybe Aurelia-Interface will have that too.&lt;/li&gt;
&lt;li&gt;the startup time of the application was quite slow (several seconds) with both
solutions. Maybe there is a way to improve that, I admit I haven't dug into it
yet.&lt;/li&gt;
&lt;li&gt;webpack is awesome ;-)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the end, ionic has a good cli, documentation and some bindings for Cordova
which make it complete and interesting. But in my opinion, the
Aurelia/Framework7 feels more natural mostly because of the weird design choices of
Angular2 and ionic has lots of custom element over HTML.&lt;/p&gt;
&lt;p&gt;Maybe I should start something (skeleton and command line tool) to work with
Aurelia, Framework7 and Cordova. If there's no news of Aurelia-Interface soon, I
think it's highly probable that I'll try. I'll update this post if I do (or
decide not to).&lt;/p&gt;
&lt;/div&gt;
</content><category term="Aurelia"></category><category term="ionic2"></category><category term="angular2"></category><category term="aurelia"></category><category term="framework7"></category><category term="android"></category><category term="mobile"></category></entry><entry><title>Fichiers service pour seafile</title><link href="//www.jujens.eu/posts/2015/Nov/21/service-files-seafile/" rel="alternate"></link><published>2015-11-21T00:00:00+01:00</published><updated>2015-11-21T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-21:/posts/2015/Nov/21/service-files-seafile/</id><summary type="html">&lt;p&gt;J'ai écrit des fichiers services pour utiliser seafile plus facilement avec
systemd (à placer dans &lt;tt class="docutils literal"&gt;/etc/systemd/system/&lt;/tt&gt;). Vous pouvez les télécharger :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seafile.service"&gt;Seafile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seahub.service"&gt;Seahub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;The seafile cloud service&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;forking&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/pids/seaf-server.pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;J'ai écrit des fichiers services pour utiliser seafile plus facilement avec
systemd (à placer dans &lt;tt class="docutils literal"&gt;/etc/systemd/system/&lt;/tt&gt;). Vous pouvez les télécharger :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seafile.service"&gt;Seafile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seahub.service"&gt;Seahub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;The seafile cloud service&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;forking&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/pids/seaf-server.pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seafile.sh start&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seafile.sh stop&lt;/span&gt;


&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;basic.target&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;The seafile cloud service (web interface)&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile.service&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile.service&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;forking&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seahub.sh start-fastcgi&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seahub.sh stop&lt;/span&gt;


&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;basic.target&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="systemd"></category><category term="seafile"></category></entry><entry><title>Fichiers service pour seafile</title><link href="//www.jujens.eu/posts/en/2015/Nov/21/service-files-seafile/" rel="alternate"></link><published>2015-11-21T00:00:00+01:00</published><updated>2015-11-21T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-21:/posts/en/2015/Nov/21/service-files-seafile/</id><summary type="html">&lt;p&gt;I wrote service files to use seafile easily with systemd (put them in
&lt;tt class="docutils literal"&gt;/etc/systemd/system/&lt;/tt&gt;). You can download them:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seafile.service"&gt;Seafile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seahub.service"&gt;Seahub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;The seafile cloud service&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;forking&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/pids/seaf-server.pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;I wrote service files to use seafile easily with systemd (put them in
&lt;tt class="docutils literal"&gt;/etc/systemd/system/&lt;/tt&gt;). You can download them:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seafile.service"&gt;Seafile&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/service-files-seafile/seahub.service"&gt;Seahub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;The seafile cloud service&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mariadb.service&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;forking&lt;/span&gt;
&lt;span class="na"&gt;PIDFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/pids/seaf-server.pid&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seafile.sh start&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seafile.sh stop&lt;/span&gt;


&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;basic.target&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[Unit]&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;The seafile cloud service (web interface)&lt;/span&gt;
&lt;span class="na"&gt;Requires&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile.service&lt;/span&gt;
&lt;span class="na"&gt;After&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile.service&lt;/span&gt;


&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;forking&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;seafile&lt;/span&gt;
&lt;span class="na"&gt;ExecStart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seahub.sh start-fastcgi&lt;/span&gt;
&lt;span class="na"&gt;ExecStop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/var/www/haiwen/seafile-server-latest/seahub.sh stop&lt;/span&gt;


&lt;span class="k"&gt;[Install]&lt;/span&gt;
&lt;span class="na"&gt;WantedBy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;basic.target&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="systemd"></category><category term="seafile"></category></entry><entry><title>Utiliser un tableau dans un Makefile</title><link href="//www.jujens.eu/posts/2015/Nov/12/array-makefile/" rel="alternate"></link><published>2015-11-12T00:00:00+01:00</published><updated>2015-11-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-12:/posts/2015/Nov/12/array-makefile/</id><summary type="html">&lt;p&gt;J'ai récemment eu besoin de lancer une tâche &lt;tt class="docutils literal"&gt;make&lt;/tt&gt; pour plusieurs
arguments. Je me suis demandé si on pouvait dans le Makefile, en passant une
variable en argument sous la forme &lt;tt class="docutils literal"&gt;portals=geojb,n16&lt;/tt&gt;, répéter une tâche
plusieurs fois. Pour cela, il faut réussir à boucler sur l'entrée. Cela se …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai récemment eu besoin de lancer une tâche &lt;tt class="docutils literal"&gt;make&lt;/tt&gt; pour plusieurs
arguments. Je me suis demandé si on pouvait dans le Makefile, en passant une
variable en argument sous la forme &lt;tt class="docutils literal"&gt;portals=geojb,n16&lt;/tt&gt;, répéter une tâche
plusieurs fois. Pour cela, il faut réussir à boucler sur l'entrée. Cela se fait
comme suit :&lt;/p&gt;
&lt;pre class="code Makefile literal-block"&gt;
&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;toto&lt;/span&gt;
&lt;span class="nf"&gt;toto&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
     &amp;#64;echo &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;portals&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
     &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; portal in &lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;portals&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;         &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;{portal}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;         &lt;span class="k"&gt;$(&lt;/span&gt;call process_portal, &lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;portal&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="cp"&gt;define process_portal
&lt;/span&gt;     &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;processing &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;done&amp;quot;&lt;/span&gt;
&lt;span class="cp"&gt;endef
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note : on peut tout à fait passer les arguments multiples sous la forme
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;portals=&amp;quot;geojb&lt;/span&gt; n16&amp;quot;&lt;/tt&gt;. Il faut alors supprimer la ligne &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;IFS=','&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;On notera que c'est beaucoup plus facile avec &lt;a class="reference external" href="https://github.com/ShaneKilkelly/manuel"&gt;manuel&lt;/a&gt; (un petit lanceur de tâche écrit en
moins de 150 lignes de bash que j'ai décidé d'utiliser à la place de make) :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#! /usr/bin/env bash
&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; hello &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; portal in &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        process &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;portal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;function&lt;/span&gt; _process &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;processing &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;done&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="make"></category></entry><entry><title>Tips for libvirt/virtmanager</title><link href="//www.jujens.eu/posts/en/2015/Nov/12/libvirt/" rel="alternate"></link><published>2015-11-12T00:00:00+01:00</published><updated>2015-11-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-12:/posts/en/2015/Nov/12/libvirt/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#static-ip" id="id1"&gt;Static IP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#launch-virtual-machine-manager-without-a-root-password" id="id2"&gt;Launch Virtual Machine manager without a root password&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#compress-qcow2-images" id="id3"&gt;Compress QCOW2 images&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#linux-guest" id="id4"&gt;Linux guest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#windows-guest" id="id5"&gt;Windows guest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="static-ip"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Static IP&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can affect a static IP to a guest of a libvirt instance with the following
command:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
virsh net-update default add ip-dhcp-host &lt;span class="s2"&gt;&amp;quot;&amp;lt;host mac='52:54:00:7d:2a:5e' …&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#static-ip" id="id1"&gt;Static IP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#launch-virtual-machine-manager-without-a-root-password" id="id2"&gt;Launch Virtual Machine manager without a root password&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#compress-qcow2-images" id="id3"&gt;Compress QCOW2 images&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#linux-guest" id="id4"&gt;Linux guest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#windows-guest" id="id5"&gt;Windows guest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="static-ip"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Static IP&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can affect a static IP to a guest of a libvirt instance with the following
command:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
virsh net-update default add ip-dhcp-host &lt;span class="s2"&gt;&amp;quot;&amp;lt;host mac='52:54:00:7d:2a:5e' name='leap' ip='192.168.122.42' /&amp;gt;&amp;quot;&lt;/span&gt; --live --config
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="launch-virtual-machine-manager-without-a-root-password"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Launch Virtual Machine manager without a root password&lt;/a&gt;&lt;/h2&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Add the users that need to do this to the &lt;tt class="docutils literal"&gt;libvirt&lt;/tt&gt; group.&lt;/li&gt;
&lt;li&gt;Create a new polkit rule in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/polkit-1/rules.d/10-libvirt.rules&lt;/span&gt;&lt;/tt&gt;
containing:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;polkit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addRule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;org.libvirt.unix.manage&amp;quot;&lt;/span&gt;
         &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;
         &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;
         &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isInGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;libvirt&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;polkit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;YES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="compress-qcow2-images"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Compress QCOW2 images&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="linux-guest"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Linux guest&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Run in the guest:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;fstrim &lt;span class="pre"&gt;-av&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;dd &lt;span class="pre"&gt;if=/dev/zero&lt;/span&gt; &lt;span class="pre"&gt;of=/mytempfile&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-f&lt;/span&gt; /mytempfile&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Run on the host:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;mv image.qcow2 image.qcow2_backup&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; convert &lt;span class="pre"&gt;-O&lt;/span&gt; qcow2 image.qcow2_backup image.qcow2&lt;/tt&gt; or if you want compression to further reduce the disk size but reduce performance: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; convert &lt;span class="pre"&gt;-O&lt;/span&gt; qcow2 &lt;span class="pre"&gt;-c&lt;/span&gt; image.qcow2_backup image.qcow2&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then boot your machine and check everything is OK.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="windows-guest"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Windows guest&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Run in the guest:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;The defragementer tool&lt;/li&gt;
&lt;li&gt;Download &lt;a class="reference external" href="https://docs.microsoft.com/fr-fr/sysinternals/downloads/sdelete"&gt;sdelete&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;tt class="docutils literal"&gt;sedelete &lt;span class="pre"&gt;-z&lt;/span&gt; c:&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Run on the host:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;mv image.qcow2 image.qcow2_backup&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; convert &lt;span class="pre"&gt;-O&lt;/span&gt; qcow2 image.qcow2_backup image.qcow2&lt;/tt&gt; or if you want compression to further reduce the disk size but reduce performance: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-img&lt;/span&gt; convert &lt;span class="pre"&gt;-O&lt;/span&gt; qcow2 &lt;span class="pre"&gt;-c&lt;/span&gt; image.qcow2_backup image.qcow2&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then boot your machine and check everything is OK.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Virtualization"></category><category term="libvirt"></category><category term="virtmanager"></category></entry><entry><title>Afficher un SVG progressivement avec reveal.js</title><link href="//www.jujens.eu/posts/2015/Nov/12/revealjs-svg-fragments/" rel="alternate"></link><published>2015-11-12T00:00:00+01:00</published><updated>2015-11-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-12:/posts/2015/Nov/12/revealjs-svg-fragments/</id><summary type="html">&lt;p&gt;Pour cela, il faut commencer par installer un plugin : &lt;a class="reference external" href="https://gist.github.com/bollwyvl/fe1d2806449487cdf88a"&gt;svg fragments&lt;/a&gt;. Dans votre
installation reveal, dans le sous dossier plugin, cloner le dépôt :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git clone https://gist.github.com/bollwyvl/fe1d2806449487cdf88a
&lt;/pre&gt;
&lt;p&gt;Ensuite, chargez le plugin :&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Ajoutez la bibliothèque D3 &lt;tt class="docutils literal"&gt;&amp;lt;script &lt;span class="pre"&gt;src=&amp;quot;reveal/js/d3.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/tt&gt; (à
&lt;a class="reference external" href="https://raw.githubusercontent.com/mbostock/d3/master/d3.min.js"&gt;télécharger séparément …&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;p&gt;Pour cela, il faut commencer par installer un plugin : &lt;a class="reference external" href="https://gist.github.com/bollwyvl/fe1d2806449487cdf88a"&gt;svg fragments&lt;/a&gt;. Dans votre
installation reveal, dans le sous dossier plugin, cloner le dépôt :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git clone https://gist.github.com/bollwyvl/fe1d2806449487cdf88a
&lt;/pre&gt;
&lt;p&gt;Ensuite, chargez le plugin :&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Ajoutez la bibliothèque D3 &lt;tt class="docutils literal"&gt;&amp;lt;script &lt;span class="pre"&gt;src=&amp;quot;reveal/js/d3.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/tt&gt; (à
&lt;a class="reference external" href="https://raw.githubusercontent.com/mbostock/d3/master/d3.min.js"&gt;télécharger séparément&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Activez le plugin en ajoutant dans l'objet de configuration de reveal (celui
passé à &lt;tt class="docutils literal"&gt;Reveal.initialize&lt;/tt&gt;) :&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'reveal/plugin/svg-fragments/reveal-svg-fragment.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;condition&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'[data-svg-fragment]'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
           &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Puis dans votre SVG ajoutez un tag comme celui-ci &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;inkscape:label=&amp;quot;fragment1&amp;quot;&lt;/span&gt;&lt;/tt&gt;
sur les éléments à faire apparaître progressivement. Vous pouvez voir un
&lt;a class="reference external" href="https://gist.githubusercontent.com/bollwyvl/fe1d2806449487cdf88a/raw/9ab4c5e38f1ea68b3afaf0c1dee998a89229a8d4/test.svg"&gt;exemple complet sur github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enfin, ajoutez le code correspondant dans votre html. Par exemple, pour le
&lt;tt class="docutils literal"&gt;test.svg&lt;/tt&gt; précédent :&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;data-svg-fragment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;test.svg#[*|label=base]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fragment&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;[*|label=fragment1]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fragment&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;[*|label=fragment2]&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Disponible &lt;a class="reference external" href="https://gist.githubusercontent.com/bollwyvl/fe1d2806449487cdf88a/raw/9ab4c5e38f1ea68b3afaf0c1dee998a89229a8d4/index.html"&gt;complètement sur github&lt;/a&gt;.&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="reveal.js"></category><category term="SVG"></category><category term="présentation"></category></entry><entry><title>Utiliser un tableau dans un Makefile</title><link href="//www.jujens.eu/posts/en/2015/Nov/12/array-makefile/" rel="alternate"></link><published>2015-11-12T00:00:00+01:00</published><updated>2015-11-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-12:/posts/en/2015/Nov/12/array-makefile/</id><summary type="html">&lt;p&gt;I recently had to launch a make target for multiple arguments. I tried to do it
in a Makefile :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Pass the arguments to loop over &lt;tt class="docutils literal"&gt;portals=geojb,n16&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Loop in the Makefile&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It turned out to be harder than I thought:&lt;/p&gt;
&lt;pre class="code Makefile literal-block"&gt;
&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;toto&lt;/span&gt;
&lt;span class="nf"&gt;toto&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
     &amp;#64;echo &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;portals&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
     &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; portal in …&lt;/pre&gt;</summary><content type="html">&lt;p&gt;I recently had to launch a make target for multiple arguments. I tried to do it
in a Makefile :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Pass the arguments to loop over &lt;tt class="docutils literal"&gt;portals=geojb,n16&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Loop in the Makefile&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It turned out to be harder than I thought:&lt;/p&gt;
&lt;pre class="code Makefile literal-block"&gt;
&lt;span class="nf"&gt;.PHONY&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;toto&lt;/span&gt;
&lt;span class="nf"&gt;toto&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
     &amp;#64;echo &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;portals&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
     &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; portal in &lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;portals&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;         &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;{portal}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;         &lt;span class="k"&gt;$(&lt;/span&gt;call process_portal, &lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;portal&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="cp"&gt;define process_portal
&lt;/span&gt;     &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;processing &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;     &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;done&amp;quot;&lt;/span&gt;
&lt;span class="cp"&gt;endef
&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note: it is possible to pass the arguments like: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;portals=&amp;quot;geojb&lt;/span&gt; n16&amp;quot;&lt;/tt&gt;. In
this case, you must remove the line &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;IFS=','&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;I noted that it is much easier with &lt;a class="reference external" href="https://github.com/ShaneKilkelly/manuel"&gt;manuel&lt;/a&gt; (a small task launcher written in
fewer than 150 lines of Bash which I decided to use instead of make):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#! /usr/bin/env bash
&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; hello &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; portal in &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        process &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;portal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;function&lt;/span&gt; _process &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;processing &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;done&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="make"></category></entry><entry><title>Se connecter à une machine virtuelle sous VirtualBox</title><link href="//www.jujens.eu/posts/2015/Nov/09/VirtualBox-connect-guest/" rel="alternate"></link><published>2015-11-09T00:00:00+01:00</published><updated>2015-11-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-09:/posts/2015/Nov/09/VirtualBox-connect-guest/</id><summary type="html">&lt;p&gt;J'ai récemment eu besoin de créer un serveur pour faire des tests de déploiement
en production pour le travail. Ce serveur est une machine virtuelle créée avec
&lt;a class="reference external" href="http://virtualbox.org/"&gt;VirtualBox&lt;/a&gt; sous Fedora 22.&lt;/p&gt;
&lt;p&gt;Pour que les tests soient concluant, je dois pouvoir me connecter à cette
machine via SSH. Voici la méthode …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai récemment eu besoin de créer un serveur pour faire des tests de déploiement
en production pour le travail. Ce serveur est une machine virtuelle créée avec
&lt;a class="reference external" href="http://virtualbox.org/"&gt;VirtualBox&lt;/a&gt; sous Fedora 22.&lt;/p&gt;
&lt;p&gt;Pour que les tests soient concluant, je dois pouvoir me connecter à cette
machine via SSH. Voici la méthode que j'ai suivie :&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Dans &lt;em&gt;File &amp;gt; Preferences &amp;gt; Network&lt;/em&gt;, sous l'onglet &lt;em&gt;Host-only Networks&lt;/em&gt;,
cliquez sur le bouton ajouter. Cette adaptateur sera utilisé par l'hôte et
l'invité pour être sur un même réseau privé.&lt;/li&gt;
&lt;li&gt;Dans les préférences de la machines, allez dans &lt;em&gt;Network&lt;/em&gt;. Activez un
adaptateur non encore utiliser et paramétrez le comme suit :&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;em&gt;Attached to:&lt;/em&gt; choisissez &lt;em&gt;Host-only Adapter&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Name&lt;/em&gt; devrait être mis automatiquement à l'adaptateur créé
précédemment. Si ce n'est pas le cas, corriger le paramètre.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On peut maintenant démarrer la machine virtuelle. Dans une console, tapez &lt;tt class="docutils literal"&gt;ip
a&lt;/tt&gt; pour récupérer son adresse ip. Vous pouvez l'utiliser pour vous connectez à
la machine virtuelle. Vous pouvez également la renseigner dans &lt;tt class="docutils literal"&gt;/etc/hosts&lt;/tt&gt;
pour avoir un nom plus facile à retenir et faciliter la configuration de votre
serveur HTTP.&lt;/p&gt;
&lt;p&gt;Et c'est tout !&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="VirtualBox"></category><category term="Virtualisation"></category></entry><entry><title>Connect to a VirtualBox VM</title><link href="//www.jujens.eu/posts/en/2015/Nov/09/VirtualBox-connect-guest/" rel="alternate"></link><published>2015-11-09T00:00:00+01:00</published><updated>2015-11-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-09:/posts/en/2015/Nov/09/VirtualBox-connect-guest/</id><summary type="html">&lt;p&gt;I recently had to create a server to perform deployment tests for work. This
server is a virtual machine created with &lt;a class="reference external" href="http://virtualbox.org/"&gt;VirtualBox&lt;/a&gt;
and runs Fedora 22.&lt;/p&gt;
&lt;p&gt;For the tests to be realistic, I had to connect with SSH to the VM. Here is the
method I followed:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;In &lt;em&gt;File &amp;gt; Preferences …&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;p&gt;I recently had to create a server to perform deployment tests for work. This
server is a virtual machine created with &lt;a class="reference external" href="http://virtualbox.org/"&gt;VirtualBox&lt;/a&gt;
and runs Fedora 22.&lt;/p&gt;
&lt;p&gt;For the tests to be realistic, I had to connect with SSH to the VM. Here is the
method I followed:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;In &lt;em&gt;File &amp;gt; Preferences &amp;gt; Network&lt;/em&gt;, under the &lt;em&gt;Host-only Networks&lt;/em&gt; tab,
click on the add button. This adapter will be used by the host and the guest
to communicate on the same private network.&lt;/li&gt;
&lt;li&gt;In the machine settings, go in &lt;em&gt;Network&lt;/em&gt;. Activate a new adapter and
configure it like this:&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;em&gt;Attached to:&lt;/em&gt; choose &lt;em&gt;Host-only Adapter&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Name&lt;/em&gt; should be set automatically on the adapter you previously
created. If it is not, set its value manually.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can now boot the machine. In a terminal, type &lt;tt class="docutils literal"&gt;ip a&lt;/tt&gt; to get the ip address
fo the VM. You can now connect to the VW with SSH and do HTTP requests to you VM
server. You should put the ip address in your &lt;tt class="docutils literal"&gt;/tc/hosts&lt;/tt&gt; to have a easy to
remember name and to ease the configuration of your HTTP server.&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="VirtualBox"></category><category term="Virtualisation"></category></entry><entry><title>Se connecter en wifi à une raspberry pi</title><link href="//www.jujens.eu/posts/2015/Nov/08/rpi-wifi/" rel="alternate"></link><published>2015-11-08T00:00:00+01:00</published><updated>2015-11-08T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-11-08:/posts/2015/Nov/08/rpi-wifi/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#connexion" id="id1"&gt;Connexion&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#rendre-la-configuration-permanente" id="id2"&gt;Rendre la configuration permanente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-son-router" id="id3"&gt;Configurer son router&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#en-complement" id="id4"&gt;En complément&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#problemes-possibles" id="id5"&gt;Problèmes possibles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Par défaut la raspi peut communiquer en Ethernet mais on peut brancher sur un de
ses ports USB un petit dongle wifi pour communiquer sans fil (cela se présente
comme une petite clé USB). J'ai pour ma …&lt;/p&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#connexion" id="id1"&gt;Connexion&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#rendre-la-configuration-permanente" id="id2"&gt;Rendre la configuration permanente&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-son-router" id="id3"&gt;Configurer son router&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#en-complement" id="id4"&gt;En complément&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#problemes-possibles" id="id5"&gt;Problèmes possibles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Par défaut la raspi peut communiquer en Ethernet mais on peut brancher sur un de
ses ports USB un petit dongle wifi pour communiquer sans fil (cela se présente
comme une petite clé USB). J'ai pour ma part acheté un Edimax EW-7811Un.&lt;/p&gt;
&lt;p&gt;Normalement rien de très compliqué. Je détaille ici la procédure pour
Archlinux. Pour une autre distribution, les manipulations devraient être
similaires.&lt;/p&gt;
&lt;p&gt;NB : il est tout à fait possible de tout configurer sans écran via SSH en étant
relié par &lt;a class="reference external" href="//www.jujens.eu/posts/2014/Jan/12/relier-rpi-pc-ethernet/"&gt;éthernet à la raspi&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="connexion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Connexion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Normalement, il suffit de brancher le dongle et de démarrer la raspi. Pour
tester que tout est correct, vous pouvez utiliser la commande suivante :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
wifi-menu -o
&lt;/pre&gt;
&lt;p&gt;Vous devriez voir la liste de tous les réseaux wifi disponibles et pouvoir vous
connecter au votre.&lt;/p&gt;
&lt;p&gt;Voir &lt;a class="reference internal" href="#problemes-possibles"&gt;Problèmes possibles&lt;/a&gt; si ça ne marche pas.&lt;/p&gt;
&lt;div class="section" id="rendre-la-configuration-permanente"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id2"&gt;Rendre la configuration permanente&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Nous allons utiliser &lt;tt class="docutils literal"&gt;netctl&lt;/tt&gt; pour nous connecter automatiquement en wifi à
notre réseau. Pour cela, nous allons utiliser un profil pré-rempli fournit avec
&lt;tt class="docutils literal"&gt;netctl&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /etc/netctl
cp examples/wireless-wpa .
vim wireless-wap &lt;span class="c1"&gt;# Éditer le fichier pour renseigner le SSID et la clé
&lt;/span&gt;netctl start wireless-wpa &lt;span class="c1"&gt;# Démarre netctl, vous devriez pouvoir utiliser le wifi
&lt;/span&gt;netctl &lt;span class="nb"&gt;enable&lt;/span&gt; wireless-wpa &lt;span class="c1"&gt;# Active netctl au démarrage.&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour plus d'informations sur &lt;tt class="docutils literal"&gt;netctl&lt;/tt&gt; voir &lt;a class="reference external" href="https://wiki.archlinux.org/index.php/Netctl"&gt;la page de wiki d'Archlinux&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-son-router"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Configurer son router&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pour que la solution soit vraiment pratique, il reste à configurer le routeur
wifi pour qu'il donne une ip fixe à la raspi. Cela permettra de renseigner
l'adresse de la raspi dans le &lt;tt class="docutils literal"&gt;/etc/hosts&lt;/tt&gt; et de pouvoir l'utiliser
facilement.&lt;/p&gt;
&lt;p&gt;Dans le cas de ma BBox, il faut aller sur &lt;a class="reference external" href="http://192.168.1.254/"&gt;http://192.168.1.254/&lt;/a&gt; puis
configuration du routeur puis DHCP. L'interface permet facilement d'associer une
ip à une adresse MAC. Si vous êtes fleimard comme moi, vous connectez la raspi
au réseau puis choisissez sa MAC dans la liste déroulante avant de la
redémarrer.&lt;/p&gt;
&lt;img alt="L'interface d'administration du serveur DHCP de ma BBox" src="/images/bbox-dhcp.png" style="width: 90%;" /&gt;
&lt;p&gt;Et voilà ! Si vous avez des questions, vous pouvez laisser un commentaire.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="en-complement"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;En complément&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/posts/2014/Jan/12/relier-rpi-pc-ethernet/"&gt;Relier sa Raspberry Pi à son PC directement en Ethernet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="problemes-possibles"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Problèmes possibles&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Si la raspi ne détecte pas votre carte wifi (possible si votre noyau est un peu
ancien), il faut installer le driver à la main. Sous Archlinux, vous pouvez utiliser&lt;/p&gt;
&lt;pre class="literal-block"&gt;
pacman -Sy dkms-8192cu
&lt;/pre&gt;
&lt;p&gt;pour l'installer. La compilation du module noyau prend un peu de temps (~12
minutes chez moi). Si la compilation rate car la fonction &lt;tt class="docutils literal"&gt;strnicmp&lt;/tt&gt; n'est pas
trouvé, utiliser la version &lt;a class="reference external" href="https://github.com/Jenselme/8192cu-dkms"&gt;patchée du module&lt;/a&gt;. Pour l'installer :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
git clone https://github.com/Jenselme/8192cu-dkms.git
&lt;span class="nb"&gt;cd&lt;/span&gt; 8192cu-dkms
makepkg -si
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Arduino - RPi - Robotique"></category><category term="Rpi"></category><category term="wifi"></category><category term="Raspberry Pi"></category></entry><entry><title>Utiliser istanbul pour voir le code coverage de tests lancés avec protractor</title><link href="//www.jujens.eu/posts/2015/Sep/25/code-coverage-istanbul-protractor/" rel="alternate"></link><published>2015-09-25T00:00:00+02:00</published><updated>2015-09-25T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-09-25:/posts/2015/Sep/25/code-coverage-istanbul-protractor/</id><summary type="html">&lt;p&gt;Récemment j'ai eu besoin d'avoir du code coverage (assuré par &lt;a class="reference external" href="https://github.com/gotwarlost/istanbul"&gt;istanbul&lt;/a&gt;) pour des tests d'intégration d'une
application AngularJS. Ces tests sont lancés avec &lt;a class="reference external" href="http://angular.github.io/protractor/"&gt;protractor&lt;/a&gt; et ce n'est pas aussi simple qu'il n'y
parait. L'idée de base est :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;D'associer une fonction à la clé &lt;tt class="docutils literal"&gt;onPrepare&lt;/tt&gt; dans la configuration de
protractor. Dans …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Récemment j'ai eu besoin d'avoir du code coverage (assuré par &lt;a class="reference external" href="https://github.com/gotwarlost/istanbul"&gt;istanbul&lt;/a&gt;) pour des tests d'intégration d'une
application AngularJS. Ces tests sont lancés avec &lt;a class="reference external" href="http://angular.github.io/protractor/"&gt;protractor&lt;/a&gt; et ce n'est pas aussi simple qu'il n'y
parait. L'idée de base est :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;D'associer une fonction à la clé &lt;tt class="docutils literal"&gt;onPrepare&lt;/tt&gt; dans la configuration de
protractor. Dans cette fonction on définit un rapporteur qui va pour chaque
test collecter le code coverage.&lt;/li&gt;
&lt;li&gt;D'utiliser un plugin (&lt;a class="reference external" href="https://gist.github.com/jbarrus/286cee4294a6537e8217"&gt;l'idée initiale est de Jeffrey Barrus&lt;/a&gt;) afin d'attendre que
le rapport soit écrit (via une promise). En effet, protractor dispose
d'une option &lt;tt class="docutils literal"&gt;onComplete&lt;/tt&gt; qui est une fonction appelée lorsque les tests
sont terminés. Cependant, cette fonction ne supporte pas l'asynchronisme :
elle ne supporte pas les callbacks et ne va pas attendre qu'une promise soit
résolue. Par conséquent, il est possible que le processus de protractor se
termine avant que le rapport ne soit écrit ou que istanbul n'ait reçu les
données de coverage. Heureusement, la méthode &lt;tt class="docutils literal"&gt;tearDown&lt;/tt&gt; d'un plugin peut
retourner une promise et protractor attendra sa résolution avant de quitter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je suppose que vous savez comment préparer vos fichiers javascript pour istanbul
(étape appelée instrumentation). Si ce n'est pas le cas, vous pouvez lire la
&lt;a class="reference external" href="https://github.com/gotwarlost/istanbul"&gt;doc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Les configurations sont les suivantes (disponibles en &lt;a class="reference internal" href="#telechargement"&gt;téléchargement&lt;/a&gt; en fin
d'article) :&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;istanbul&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'istanbul'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;collector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;istanbul&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Collector&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;waitPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./waitPlugin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;    &lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Coverage report successfully written'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;  &lt;span class="nx"&gt;specs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;    &lt;span class="s1"&gt;'../test/integration/*.spec.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;    &lt;span class="s1"&gt;'../test/selenium/*_test.js'&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;  &lt;span class="nx"&gt;seleniumAddress&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'${seleniumAddress}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;  &lt;span class="nx"&gt;maxSessions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;  &lt;span class="nx"&gt;multiCapabilities&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;browserName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'firefox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shardTestFiles&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxInstances&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;  &lt;span class="nx"&gt;framework&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'jasmine2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'./waitPlugin.js'&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;  &lt;span class="nx"&gt;onPrepare&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;jasmineEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jasmine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;    &lt;span class="nx"&gt;waitPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setOnComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;    &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;    &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'${testPortalAddress}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;    &lt;span class="nx"&gt;jasmineEnv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addReporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;specDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'failed'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/ /g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;reportfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'coverage/integration/json/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;          &lt;span class="nx"&gt;reporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;istanbul&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reportfile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;executeScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'return __coverage__;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;                  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coverageResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;                    &lt;span class="nx"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coverageResults&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;                  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;          &lt;span class="nx"&gt;waitPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;45 &lt;/span&gt;      &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="ln"&gt;46 &lt;/span&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;On commence par charger les modules (istanbul, le collecteur, le plugin). On
crée également la variable &lt;tt class="docutils literal"&gt;reporter&lt;/tt&gt;. Elle contiendra par la suite un
objet utilisé dans différentes fonctions.&lt;/li&gt;
&lt;li&gt;Ensuite on crée la fonction &lt;tt class="docutils literal"&gt;report&lt;/tt&gt; qui sera utilisé par la suite pour
écrire le rapport. Pour cela, on donne le format du rapport (ici
json). Plusieurs formats sont supportés et istanbul peut générer un rapport
dans plusieurs formats à la fois.&lt;/li&gt;
&lt;li&gt;Dans la configuration de protractor, rien de particulier jusqu'à la ligne 27
pour la fonction &lt;tt class="docutils literal"&gt;onPrepare&lt;/tt&gt;.&lt;ol class="arabic"&gt;
&lt;li&gt;À la ligne 29, on définit la fonction à appeler une fois que toutes les
promises du plugin «&amp;nbsp;attendre&amp;nbsp;» sont résolues, en l'occurrence notre
fonction &lt;tt class="docutils literal"&gt;report&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;À la ligne 33, on ajoute un rapporteur à jasmine, le framework de
tests. Ce rapporteur comprend une méthode &lt;tt class="docutils literal"&gt;specDone&lt;/tt&gt; qui est appelée
(comme son nom l'indique) à chaque fois qu'un spec est terminé. Si les
tests ont réussi, on récupère le code coverage depuis la variable globale
&lt;tt class="docutils literal"&gt;__coverage__&lt;/tt&gt; de istanbul et on ajoute le résultat au collecteur. Ces
opérations étant asynchrone et renvoyant une promise, on ajoute cette
dernière à la liste de promises à attendre dans notre plugin.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pour le plugin wait, rien de très compliqué, je pense que le code parle de lui
même. Pensez simplement à installer la bibliothèque &lt;tt class="docutils literal"&gt;q&lt;/tt&gt; dont dépend le script
avec &lt;tt class="docutils literal"&gt;npm install q&lt;/tt&gt; ou &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;--save&lt;/span&gt; q&lt;/tt&gt; pour ajouter &lt;tt class="docutils literal"&gt;q&lt;/tt&gt; à votre
&lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt;. En cas de problèmes, vous pouvez laisser un commentaire.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'q'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;waitList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;waitList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setOnComplete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;  &lt;span class="nx"&gt;onComplete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teardown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;waitList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Si comme moi, vous devez lancer chaque fichier spec dans un nouveau navigateur,
pour avoir la couverture globale, vous devez écrire le résultat de chaque jeu de
tests dans un fichier json puis rassembler les résultats (par exemple en un
rapport html plus lisible) avec la commande suivante :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
istanbul report --include &lt;span class="s1"&gt;'coverage/integration/json/**/*.json'&lt;/span&gt; --dir &lt;span class="s1"&gt;'coverage/integration'&lt;/span&gt;  html
&lt;/pre&gt;
&lt;p&gt;Si en revanche vous pouvez lancer tous les tests dans un seul navigateur, vous
pouvez récupérer le rapport au format HTML directement en changeant ligne 8 de
la configuration de protractor &lt;tt class="docutils literal"&gt;json&lt;/tt&gt; en &lt;tt class="docutils literal"&gt;html&lt;/tt&gt;.&lt;/p&gt;
&lt;div class="section" id="telechargements"&gt;
&lt;h2&gt;Téléchargements&lt;/h2&gt;
&lt;ul class="simple" id="telechargement"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/istanbul-protractor/protractor-conf.js"&gt;protractor-conf.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/istanbul-protractor/waitPlugin.js"&gt;waitPlugin.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;À réutiliser sans modération !&lt;/p&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="istanbul"></category><category term="javascript"></category><category term="protractor"></category><category term="AngularJS"></category><category term="code coverage"></category></entry><entry><title>Use istanbul to get code coverage of integration tests launched with protractor</title><link href="//www.jujens.eu/posts/en/2015/Sep/25/code-coverage-istanbul-protractor/" rel="alternate"></link><published>2015-09-25T00:00:00+02:00</published><updated>2015-09-25T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-09-25:/posts/en/2015/Sep/25/code-coverage-istanbul-protractor/</id><summary type="html">&lt;p&gt;Recently, I needed code coverage (generated by &lt;a class="reference external" href="https://github.com/gotwarlost/istanbul"&gt;istanbul&lt;/a&gt;) for integration tests of an
AngularJS application. These tests are launched with &lt;a class="reference external" href="http://angular.github.io/protractor/"&gt;protractor&lt;/a&gt;. Sadly, this is not as easy as it may
sound. The idea is to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;associate a function to the &lt;tt class="docutils literal"&gt;onPrepare&lt;/tt&gt; key in protractor's
configuration. In this function, we define …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;Recently, I needed code coverage (generated by &lt;a class="reference external" href="https://github.com/gotwarlost/istanbul"&gt;istanbul&lt;/a&gt;) for integration tests of an
AngularJS application. These tests are launched with &lt;a class="reference external" href="http://angular.github.io/protractor/"&gt;protractor&lt;/a&gt;. Sadly, this is not as easy as it may
sound. The idea is to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;associate a function to the &lt;tt class="docutils literal"&gt;onPrepare&lt;/tt&gt; key in protractor's
configuration. In this function, we define a reporter which will for each test
collect the code coverage.&lt;/li&gt;
&lt;li&gt;use a plugin (&lt;a class="reference external" href="https://gist.github.com/jbarrus/286cee4294a6537e8217"&gt;the idea is from Jeffrey Barrus&lt;/a&gt;) in order to wait for
the report to be written (with a promise): protractor has a &lt;tt class="docutils literal"&gt;onComplete&lt;/tt&gt;
option (a function called once all the tests are completed). However, this
function doesn't support asynchronism: you cannot use callback or promise. So
protractor may quit before the report is written or before the reporter has
received any data. Hopefully, the &lt;tt class="docutils literal"&gt;tearDown&lt;/tt&gt; method of a plugin can return a
promise and protractor will wait its fulfillment before quitting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I suppose that you know how to prepare your js files for istanbul (this step is
called instrumentation). If you don't, you should read the &lt;a class="reference external" href="https://github.com/gotwarlost/istanbul"&gt;doc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here are the configurations (you can &lt;a class="reference internal" href="#download"&gt;download&lt;/a&gt; them at the end of the article):&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;istanbul&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'istanbul'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;collector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;istanbul&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Collector&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;waitPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./waitPlugin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;    &lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;    &lt;span class="nx"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Coverage report successfully written'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;  &lt;span class="nx"&gt;specs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;    &lt;span class="s1"&gt;'../test/integration/*.spec.js'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;    &lt;span class="s1"&gt;'../test/selenium/*_test.js'&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;20 &lt;/span&gt;  &lt;span class="nx"&gt;seleniumAddress&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'${seleniumAddress}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;21 &lt;/span&gt;  &lt;span class="nx"&gt;maxSessions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;22 &lt;/span&gt;  &lt;span class="nx"&gt;multiCapabilities&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="ln"&gt;23 &lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;browserName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'firefox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;shardTestFiles&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxInstances&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;24 &lt;/span&gt;  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="ln"&gt;25 &lt;/span&gt;  &lt;span class="nx"&gt;framework&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'jasmine2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;26 &lt;/span&gt;  &lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'./waitPlugin.js'&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="ln"&gt;27 &lt;/span&gt;  &lt;span class="nx"&gt;onPrepare&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;28 &lt;/span&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;jasmineEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jasmine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;29 &lt;/span&gt;    &lt;span class="nx"&gt;waitPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setOnComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;30 &lt;/span&gt;    &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;maximize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;31 &lt;/span&gt;    &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'${testPortalAddress}'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;32 &lt;/span&gt;
&lt;span class="ln"&gt;33 &lt;/span&gt;    &lt;span class="nx"&gt;jasmineEnv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addReporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;34 &lt;/span&gt;      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;specDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;35 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;'failed'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;36 &lt;/span&gt;          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/ /g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;37 &lt;/span&gt;          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;reportfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'coverage/integration/json/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;38 &lt;/span&gt;          &lt;span class="nx"&gt;reporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;istanbul&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reportfile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;39 &lt;/span&gt;          &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;browser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;executeScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'return __coverage__;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;40 &lt;/span&gt;                  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coverageResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;41 &lt;/span&gt;                    &lt;span class="nx"&gt;collector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coverageResults&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;42 &lt;/span&gt;                  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;43 &lt;/span&gt;          &lt;span class="nx"&gt;waitPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt;44 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;45 &lt;/span&gt;      &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="ln"&gt;46 &lt;/span&gt;    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;47 &lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;48 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;We start by charging the modules (istanbul, the collector, the plugin) and we
create the &lt;tt class="docutils literal"&gt;reporter&lt;/tt&gt; variable. It will contain the Reporter object used in
various functions.&lt;/li&gt;
&lt;li&gt;Then we create the &lt;tt class="docutils literal"&gt;report&lt;/tt&gt; function which will be used to write the
report. To do that, we specify the format of the report (json). More formats
are supported by istanbul.&lt;/li&gt;
&lt;li&gt;In protractor's configuration, nothing special until line 27 in the
&lt;tt class="docutils literal"&gt;onPrepare&lt;/tt&gt; function:&lt;ol class="arabic"&gt;
&lt;li&gt;Line 29, we define the function that must be called once all the promises
of the &lt;tt class="docutils literal"&gt;waitPlugin&lt;/tt&gt; are fulfilled (here our &lt;tt class="docutils literal"&gt;report&lt;/tt&gt; function).&lt;/li&gt;
&lt;li&gt;Line 33, we add a reporter to jasmine, our test framework. This reporter
only has a &lt;tt class="docutils literal"&gt;specDone&lt;/tt&gt; method which is called each time a spec file is
completed. If the tests were successful, we get the code coverage from the
&lt;tt class="docutils literal"&gt;__coverage__&lt;/tt&gt; global variable and we add the result to the
collector. These operation are asynchronous and return a promise. We add
this promise to the list of promise to wait for in our plugin.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the &lt;tt class="docutils literal"&gt;waitPlugin&lt;/tt&gt;, nothing special, I think the code is obvious
enough. Just think to install the &lt;tt class="docutils literal"&gt;q&lt;/tt&gt; library which is required by the plugin
to have promises. You can install it with &lt;tt class="docutils literal"&gt;npm install q&lt;/tt&gt; or &lt;tt class="docutils literal"&gt;npm
install &lt;span class="pre"&gt;--save&lt;/span&gt; q&lt;/tt&gt; if you want to save this dependency in your
&lt;tt class="docutils literal"&gt;package.json&lt;/tt&gt;. If you have questions, you can leave a comment.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="ln"&gt; 1 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'q'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="ln"&gt; 2 &lt;/span&gt;
&lt;span class="ln"&gt; 3 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;waitList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="ln"&gt; 4 &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 5 &lt;/span&gt;
&lt;span class="ln"&gt; 6 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;waitList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt; 7 &lt;/span&gt;
&lt;span class="ln"&gt; 8 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setOnComplete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 9 &lt;/span&gt;  &lt;span class="nx"&gt;onComplete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="ln"&gt;10 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="ln"&gt;11 &lt;/span&gt;
&lt;span class="ln"&gt;12 &lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teardown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;13 &lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;waitList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;14 &lt;/span&gt;      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;15 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;16 &lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;onComplete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="ln"&gt;17 &lt;/span&gt;        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;18 &lt;/span&gt;      &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="ln"&gt;19 &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If like me, you must launch each spec file in a new browser, in order to have
the global coverage, you need to write the result of each spec in a json file
and then merge all the results with the following command:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
istanbul report --include &lt;span class="s1"&gt;'coverage/integration/json/**/*.json'&lt;/span&gt; --dir &lt;span class="s1"&gt;'coverage/integration'&lt;/span&gt;  html
&lt;/pre&gt;
&lt;p&gt;If you can however launch all the tests in a single browser, you can get the
report directly in HTML by changing line 8 of protractor's configuration
(&lt;tt class="docutils literal"&gt;json&lt;/tt&gt; should become &lt;tt class="docutils literal"&gt;html&lt;/tt&gt;).&lt;/p&gt;
&lt;div class="section" id="downloads"&gt;
&lt;h2&gt;Downloads&lt;/h2&gt;
&lt;ul class="simple" id="download"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/istanbul-protractor/protractor-conf.js"&gt;protractor-conf.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/istanbul-protractor/waitPlugin.js"&gt;waitPlugin.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="istanbul"></category><category term="javascript"></category><category term="protractor"></category><category term="AngularJS"></category><category term="code coverage"></category></entry><entry><title>Utiliser postfix pour relayer ses mails vers un autre serveur</title><link href="//www.jujens.eu/posts/2015/Aug/18/postfix-relayhost/" rel="alternate"></link><published>2015-08-18T00:00:00+02:00</published><updated>2015-08-18T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-08-18:/posts/2015/Aug/18/postfix-relayhost/</id><summary type="html">&lt;p&gt;J'ai récemment eu besoin de pouvoir envoyer des mails depuis ma machine avec un
serveur de mails tournant en local. La façon la plus simple de faire ça est à
mon avis d'avoir un serveur de mail qui relaie les mails vers un autre serveur
mail. Pour des cas simples …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai récemment eu besoin de pouvoir envoyer des mails depuis ma machine avec un
serveur de mails tournant en local. La façon la plus simple de faire ça est à
mon avis d'avoir un serveur de mail qui relaie les mails vers un autre serveur
mail. Pour des cas simples (juste l'utilisation de la commande &lt;tt class="docutils literal"&gt;mail&lt;/tt&gt;,
&lt;tt class="docutils literal"&gt;ssmtp&lt;/tt&gt; est suffisant, voir configuration à la fin). Pour avoir un vrai
serveur smtp, j'ai décidé d'utiliser &lt;tt class="docutils literal"&gt;postfix&lt;/tt&gt; qui fait ça très bien et que
j'utilise sur mon serveur.&lt;/p&gt;
&lt;p&gt;En prérequis :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;installer &lt;tt class="docutils literal"&gt;postfix&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;disposer d'un autre serveur smtp sur lequel on peut se connecter (le vôtre,
Gmail, Outlook, …)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Éditer &lt;tt class="docutils literal"&gt;/etc/postfix/main.cf&lt;/tt&gt; et ajouter :&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="na"&gt;relayhost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;smtp.exemple.com:587&lt;/span&gt;
&lt;span class="na"&gt;smtpd_sasl_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;smtpd&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_password_maps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;hash:/etc/postfix/sasl_passwd&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;cyrus&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_auth_enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="na"&gt;smtp_use_tls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;

&lt;span class="c1"&gt;# Pour que le seveur ne relaie que les mails venant de localhost&lt;/span&gt;
&lt;span class="c1"&gt;# Attention, c'est le réseau 127.0.0.0/8 qui doit être utilisé et&lt;/span&gt;
&lt;span class="c1"&gt;# pas l'ip (127.0.0.1 ou 127.0.0.1/8)&lt;/span&gt;
&lt;span class="na"&gt;mynetworks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;127.0.0.0/8, [::1]/128&lt;/span&gt;
&lt;span class="na"&gt;smtpd_recipient_restrictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;permit_mynetworks, reject_unauth_destination&lt;/span&gt;

&lt;span class="c1"&gt;# Nécessaire uniquement si le serveur smtp a besoin que le mot de passe&lt;/span&gt;
&lt;span class="c1"&gt;# soit envoyé en texte clair.&lt;/span&gt;
&lt;span class="na"&gt;smtp_sasl_security_options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;noanonymous&lt;/span&gt;

&lt;span class="c1"&gt;# Nécessaire uniquement votre fournisseur utilise du load balancing et&lt;/span&gt;
&lt;span class="c1"&gt;# transfère les mails vers un autre serveur SMTP.&lt;/span&gt;
&lt;span class="na"&gt;smtp_cname_overrides_servername&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il reste ensuite à créer le fichier de mots de passes. Dans
&lt;tt class="docutils literal"&gt;/etc/postfix/sasl_passwd&lt;/tt&gt; avec :&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="na"&gt;smtp.exemple.com:587 nomutilisateur:mdp&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ensuite, utiliser la commande &lt;tt class="docutils literal"&gt;postmap &lt;span class="pre"&gt;hash:/etc/postfix/sasl_passwd&lt;/span&gt;&lt;/tt&gt; pour
générer fichier empreintes des mots passes utilisé par postfix. Vous pouvez
tester la configuration avec &lt;tt class="docutils literal"&gt;postmap &lt;span class="pre"&gt;-q&lt;/span&gt; smtp.provider.com:25
/etc/postfix/sasl_passwd&lt;/tt&gt; qui doit renvoyer &lt;tt class="docutils literal"&gt;nomutilisateur:mdp&lt;/tt&gt;. Vous pouvez
désormais supprimer &lt;tt class="docutils literal"&gt;/etc/postfix/sasl_passwd&lt;/tt&gt; et redémarrer postfix.&lt;/p&gt;
&lt;p&gt;Note : il est possible que vous ayez besoin de lancer &lt;tt class="docutils literal"&gt;newaliases&lt;/tt&gt; pour
terminer la configuration initiale du serveur.&lt;/p&gt;
&lt;p&gt;Comme j'ai écrit la conf pour ssmtp, la voilà (dans &lt;tt class="docutils literal"&gt;/etc/ssmtp/ssmtp.conf&lt;/tt&gt;) :&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="na"&gt;mailhub&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;smtp.example.com:587&lt;/span&gt;
&lt;span class="na"&gt;AuthUser&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;nomutilisateur&lt;/span&gt;
&lt;span class="na"&gt;AuthPass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;mdp&lt;/span&gt;
&lt;span class="c1"&gt;# Si le serveur utilise StartSSL, ne pas utiliser avec UseTLS=yes&lt;/span&gt;
&lt;span class="na"&gt;UseSTARTTLS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;YES&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Auto-hébergement"></category><category term="mail"></category><category term="postfix"></category></entry><entry><title>A light branching strategy with mercurial and bookmarks</title><link href="//www.jujens.eu/posts/2015/Jul/22/light-branches-mercurial-bookmarks/" rel="alternate"></link><published>2015-07-22T00:00:00+02:00</published><updated>2015-07-22T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-07-22:/posts/2015/Jul/22/light-branches-mercurial-bookmarks/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#using-bookmarks" id="id1"&gt;Using bookmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#other-mercurial-tips" id="id2"&gt;Other mercurial tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id3"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;I am a contributor to &lt;a class="reference external" href="http://nbpython.org/"&gt;nbpython&lt;/a&gt; the &lt;a class="reference external" href="http://netbeans.org"&gt;netbeans&lt;/a&gt; plugin for python. Since the DCVS used is mercurial and
I have almost exclusively used git before I add to adapt my workflow to work
properly.&lt;/p&gt;
&lt;p&gt;What I want to do:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;create a branch from …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#using-bookmarks" id="id1"&gt;Using bookmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#other-mercurial-tips" id="id2"&gt;Other mercurial tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id3"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;I am a contributor to &lt;a class="reference external" href="http://nbpython.org/"&gt;nbpython&lt;/a&gt; the &lt;a class="reference external" href="http://netbeans.org"&gt;netbeans&lt;/a&gt; plugin for python. Since the DCVS used is mercurial and
I have almost exclusively used git before I add to adapt my workflow to work
properly.&lt;/p&gt;
&lt;p&gt;What I want to do:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;create a branch from the current default branch (the equivalent of master in
git) to work on my contributions. This branch is temporary, used for
development and code review (so it must be pushed and have an easy way to
update to it) and should be deleted once the code is merge in the main trunck.&lt;/li&gt;
&lt;li&gt;the code must be &amp;quot;rebased&amp;quot; in git terminology above the latest commit in
default to preserve a linear history.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are coming from a git background, you must know that mercurial has four
branching mechanism available:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;branching by cloning: you just do a &lt;tt class="docutils literal"&gt;hg clone&lt;/tt&gt; of the repo in another
folder. This is far from efficient in term of disk space and network usage but
it is the older branching mechanism and I only present it for the sake of
completeness. I don't see the point to use it now.&lt;/li&gt;
&lt;li&gt;anonymous branch: to create such a branch, you go to a previous revision and
make a new commit. The only way to switch to this branch is with the commit
hash (hence the name anonymous). In git, you just cannot do that. If you go to
a commit that is associated with a branch, git warns you that you are in
&lt;em&gt;detached HEAD&lt;/em&gt; and that the commit you do will be discarded at some point
(probably in the next garbage collection). In mercurial, you can do this as it
allows multiple heads.&lt;/li&gt;
&lt;li&gt;named branch: again, there is no equivalent in git. Theses branches are global
and permanent: you can close them so they are not listed by default with
&lt;tt class="docutils literal"&gt;hg branches&lt;/tt&gt; (which list all the named branches) but you cannot delete
them. You create them with &lt;tt class="docutils literal"&gt;hg branch &lt;span class="pre"&gt;&amp;lt;branch-name&amp;gt;&lt;/span&gt;&lt;/tt&gt;. Furthermore, the name
of the branch will be stored with the commit metadata. This look good for long
lasting branch for some important features but this is too heavy for what I am
looking for.&lt;/li&gt;
&lt;li&gt;bookmarks: you can bookmark any change in mercurial. If a bookmark is active
and you do a commit, the bookmark will be updated to point to this
commit. Nothing is stored as metadata. This what looks more like the branch in
git and this is what I want.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="using-bookmarks"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Using bookmarks&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can easily:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;navigate to a bookmark with &lt;tt class="docutils literal"&gt;hg up &amp;lt;bookmark&amp;gt;&lt;/tt&gt; (this is the
command you use to go to any revision let it be a commit, a branch or a
bookmark)&lt;/li&gt;
&lt;li&gt;list them with &lt;tt class="docutils literal"&gt;hg bookmarks&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;delete them with &lt;tt class="docutils literal"&gt;hg bookmark &lt;span class="pre"&gt;-d&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;bookmark-name&amp;gt;&lt;/span&gt;&lt;/tt&gt;. This will only delete the
bookmark, not the commits associated with it which are still accessible with
their hashes (even if they are not merged in a named branch). See below to
learn how to do that.&lt;/li&gt;
&lt;li&gt;push them to the remote repository with &lt;tt class="docutils literal"&gt;hg push &lt;span class="pre"&gt;-B&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;bookmark-name&lt;/span&gt;&lt;/tt&gt;. This
will create the bookmark if it doesn't exist or update it if it is already
present.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One disturbing side effect when you use bookmark is that a branch will have
multiple heads. So I use the rebase extension and do a &lt;tt class="docutils literal"&gt;hg pull &lt;span class="pre"&gt;--rebase&lt;/span&gt;&lt;/tt&gt; to
get the changes from &lt;a class="reference external" href="http://hg.netbeans.org/main/contrib"&gt;http://hg.netbeans.org/main/contrib&lt;/a&gt;. If you used mercurial
before you may have done instead &lt;tt class="docutils literal"&gt;hg pull&lt;/tt&gt; and then &lt;tt class="docutils literal"&gt;hg update&lt;/tt&gt; (and
eventually &lt;tt class="docutils literal"&gt;hg merge&lt;/tt&gt; to solve conflict) or used the fetch extension and did
&lt;tt class="docutils literal"&gt;hg fetch&lt;/tt&gt; which just does all this in one command.&lt;/p&gt;
&lt;p&gt;So, how do I work?&lt;/p&gt;
&lt;p&gt;Before doing anything, I created a &lt;tt class="docutils literal"&gt;main&lt;/tt&gt; bookmark at the current state of
default so that I could go back there easily. You should do the same. Once this
is done, here's what I do:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;I do a &lt;tt class="docutils literal"&gt;hg pull &lt;span class="pre"&gt;--rebase&lt;/span&gt; netbeans&lt;/tt&gt; to get the latest code from
hg.netbeans.org (my default remote point to my bitbucket clone so I don't
push by error a bookmark on netbeans).&lt;/li&gt;
&lt;li&gt;I create a bookmark with &lt;tt class="docutils literal"&gt;hg bookmark &amp;lt;feature&amp;gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;I work and commit normally.&lt;/li&gt;
&lt;li&gt;I do a &lt;tt class="docutils literal"&gt;hg push &lt;span class="pre"&gt;-B&lt;/span&gt; &amp;lt;feature&amp;gt;&lt;/tt&gt; to push my patches to my bitbucket repo so
the other contributors can review my work.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once my changes are validated, I must rebase my changes to the top of
default. The fist way I found out was to export my changes with &lt;tt class="docutils literal"&gt;hg export &lt;span class="pre"&gt;-r&lt;/span&gt;
&amp;lt;list of revisions to export&amp;gt; &amp;gt; file.patch&lt;/tt&gt; and then do a &lt;tt class="docutils literal"&gt;hg up main&lt;/tt&gt; and
finally &lt;tt class="docutils literal"&gt;hg import &amp;lt; file.patch&lt;/tt&gt;. This worked but the &lt;tt class="docutils literal"&gt;graft&lt;/tt&gt; extension
makes it easier. &lt;tt class="docutils literal"&gt;graft&lt;/tt&gt; is the equivalent of &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;cherry-pick&lt;/span&gt;&lt;/tt&gt;. So here's what
I do:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;hg up main&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;hg graft &lt;span class="pre"&gt;-r&lt;/span&gt; &amp;lt;list of revision to export&amp;gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;hg push &lt;span class="pre"&gt;-r&lt;/span&gt; main netbeans&lt;/tt&gt; to push the new revision under the bookmark main
to hg.netbeans.org to the default branch without creating the bookmark.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now I want to delete the branch. To do that, I use the &lt;tt class="docutils literal"&gt;strip&lt;/tt&gt; extension. It
deletes a commit and all its children. So a &lt;tt class="docutils literal"&gt;hg strip &lt;span class="pre"&gt;-r&lt;/span&gt; &amp;lt;fist commit of
bookmarked branch&lt;/tt&gt; will to the trick. But it has an option to delete a
bookrmark and all its parents (until it reaches the original parent of
course). So I do: &lt;tt class="docutils literal"&gt;hg strip &lt;span class="pre"&gt;-B&lt;/span&gt; &amp;lt;feature&amp;gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="other-mercurial-tips"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Other mercurial tips&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are some tips I learned working with mercurial. There are too few of them
for a dedicated article yet. I will update this list when I learn more of them.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;To do the equivalent of &lt;tt class="docutils literal"&gt;git rebase &lt;span class="pre"&gt;-i&lt;/span&gt;&lt;/tt&gt;, use &lt;tt class="docutils literal"&gt;hg histedit &lt;span class="pre"&gt;-r&lt;/span&gt; &amp;lt;revision&amp;gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;To discard the last commit: &lt;tt class="docutils literal"&gt;hg strip &lt;span class="pre"&gt;--keep&lt;/span&gt;&lt;/tt&gt;. This will remove the last
commit from history but let the files like they were after this commit.&lt;/li&gt;
&lt;li&gt;To get &lt;tt class="docutils literal"&gt;hg st&lt;/tt&gt; to display the relative path of files, add this to your
.hgrc:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;span class="na"&gt;__mystatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;status&lt;/span&gt;
&lt;span class="na"&gt;st&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;!hg __mystatus $($HG root) $HG_ARGS&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Some extensions that I think are a must have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;pager: by default, mercurial don't page its output. So for instance if you
have lots of commits and do a &lt;tt class="docutils literal"&gt;hg log&lt;/tt&gt;, they will all be printed at
once. Not very practical. pager allow you to give the result to less.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;progress: to view the progress of network operation (like push, pull,
clone). Sadly not enabled by default. Once the extension is enabled, you must
configure it:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[pager]&lt;/span&gt;
&lt;span class="na"&gt;pager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LESS='FRX' less&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To activate an extension, add it to the &lt;tt class="docutils literal"&gt;[extensions]&lt;/tt&gt; section of your .hgrc
like this:&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[extensions]&lt;/span&gt;
&lt;span class="na"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can view my complete .hgrc &lt;a class="reference external" href="https://github.com/Jenselme/dot-files-shell/blob/master/.hgrc"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Coming from git, mercurial is a bit disturbing at first. The main critic I have
is that even for things that I consider to be basic like a less pager or to view
progress of some operations you must enable some extensions. However, despite
being different, it is just a matter of habit to be at ease with mercurial. If
you haven't tried it yet, you really should:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;it works great&lt;/li&gt;
&lt;li&gt;I think that the command names are better and less confusing&lt;/li&gt;
&lt;li&gt;it has nice local number to identify commits. So instead of doing &lt;tt class="docutils literal"&gt;hg up &lt;span class="pre"&gt;-r&lt;/span&gt;
&amp;lt;hash&amp;gt;&lt;/tt&gt; you can just do &lt;tt class="docutils literal"&gt;hg up &lt;span class="pre"&gt;-r&lt;/span&gt; 78&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;it has the &lt;tt class="docutils literal"&gt;tip&lt;/tt&gt; which identify the last commit you made&lt;/li&gt;
&lt;li&gt;and many more.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="git"></category><category term="mercurial"></category></entry><entry><title>Déplacer des lignes correspondant à une regexp en bash</title><link href="//www.jujens.eu/posts/2015/Jul/22/move-lines-matching-pattern-bash/" rel="alternate"></link><published>2015-07-22T00:00:00+02:00</published><updated>2015-07-22T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-07-22:/posts/2015/Jul/22/move-lines-matching-pattern-bash/</id><summary type="html">&lt;p&gt;Récemment sur un projet j'ai dû mettre à jour &lt;a class="reference external" href="https://github.com/google/closure-compiler"&gt;closure compiler&lt;/a&gt;. Afin de faire cette mise à jour,
j'ai dû déplacer certaines lignes de code utilisées par closure : le compilateur
utilise des &lt;tt class="docutils literal"&gt;goog.require&lt;/tt&gt; et des &lt;tt class="docutils literal"&gt;goog.provide&lt;/tt&gt; pour trouver les
dépendances entre les fichiers. Dans la version utilisée par …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Récemment sur un projet j'ai dû mettre à jour &lt;a class="reference external" href="https://github.com/google/closure-compiler"&gt;closure compiler&lt;/a&gt;. Afin de faire cette mise à jour,
j'ai dû déplacer certaines lignes de code utilisées par closure : le compilateur
utilise des &lt;tt class="docutils literal"&gt;goog.require&lt;/tt&gt; et des &lt;tt class="docutils literal"&gt;goog.provide&lt;/tt&gt; pour trouver les
dépendances entre les fichiers. Dans la version utilisée par le projet, ces
lines étaient dans une IEF :&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'toto'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'titi'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Mais cette façon d'écrire le code n'est plus possible dans les versions récentes
du closure compiler : les dépendances doivent être gérées directement au niveau
du fichier. Les &lt;tt class="docutils literal"&gt;goog.require&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;goog.provide&lt;/tt&gt; doivent donc être déplacées
dans tous les fichiers en dehors de l'IEF. Vu le nombre de fichiers concernés,
j'ai écrit le script suivant pour le faire automatiquement.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Boucle&lt;/span&gt; &lt;span class="nx"&gt;sur&lt;/span&gt; &lt;span class="nx"&gt;tous&lt;/span&gt; &lt;span class="nx"&gt;les&lt;/span&gt; &lt;span class="nx"&gt;fichiers&lt;/span&gt; &lt;span class="nx"&gt;qui&lt;/span&gt; &lt;span class="nx"&gt;ont&lt;/span&gt; &lt;span class="nx"&gt;une&lt;/span&gt; &lt;span class="nx"&gt;IEF&lt;/span&gt; &lt;span class="nx"&gt;dans&lt;/span&gt; &lt;span class="nx"&gt;les&lt;/span&gt; &lt;span class="nx"&gt;sources&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rl&lt;/span&gt; &lt;span class="s1"&gt;'^(function() {'&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;grep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;On&lt;/span&gt; &lt;span class="nx"&gt;supprime&lt;/span&gt; &lt;span class="nx"&gt;la&lt;/span&gt; &lt;span class="nx"&gt;ligne&lt;/span&gt; &lt;span class="nx"&gt;de&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="s1"&gt;'IEF
    sed -i '&lt;/span&gt;&lt;span class="o"&gt;/^&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;/d' &amp;quot;${file}&amp;quot;&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;On&lt;/span&gt; &lt;span class="nx"&gt;supprime&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="s1"&gt;'indentation des goog.*
    sed -i -r '&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="o"&gt;/^&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="s1"&gt;' &amp;quot;${file}&amp;quot;
    # Affiche le fichier de bas en haut.
    # Pour la première ligne qui correspond à la gestion de dépendance, on
    # &amp;quot;imprime&amp;quot; la première ligne de l'&lt;/span&gt;&lt;span class="nx"&gt;IEF&lt;/span&gt; &lt;span class="nx"&gt;et&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;affiche&lt;/span&gt; &lt;span class="nx"&gt;la&lt;/span&gt; &lt;span class="nx"&gt;ligne&lt;/span&gt; &lt;span class="nx"&gt;de&lt;/span&gt; &lt;span class="nx"&gt;dépendance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Remet&lt;/span&gt; &lt;span class="nx"&gt;le&lt;/span&gt; &lt;span class="nx"&gt;ficher&lt;/span&gt; &lt;span class="nx"&gt;à&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="s1"&gt;'endroit.
    tac &amp;quot;${file}&amp;quot; | awk '&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nx"&gt;seen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;(function() {&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;seen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;' | tac &amp;gt; &amp;quot;${file}.new&amp;quot;
    # On doit utiliser un nouveau fichier car du fait des pipes, le fichier
    # va s'&lt;/span&gt;&lt;span class="nx"&gt;écrire&lt;/span&gt; &lt;span class="nx"&gt;avant&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;avoir&lt;/span&gt; &lt;span class="nx"&gt;été&lt;/span&gt; &lt;span class="nx"&gt;complètement&lt;/span&gt; &lt;span class="nx"&gt;lu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ce&lt;/span&gt; &lt;span class="nx"&gt;qui&lt;/span&gt; &lt;span class="nx"&gt;va&lt;/span&gt; &lt;span class="nx"&gt;tout&lt;/span&gt; &lt;span class="nx"&gt;faire&lt;/span&gt; &lt;span class="nx"&gt;planter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;mv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}.new&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}&amp;quot;&lt;/span&gt;
&lt;span class="nx"&gt;done&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Bash/Shell"></category></entry><entry><title>Supprimer la ligne encoding de fichiers python</title><link href="//www.jujens.eu/posts/2015/Jul/22/remove-encoding-python/" rel="alternate"></link><published>2015-07-22T00:00:00+02:00</published><updated>2015-07-22T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-07-22:/posts/2015/Jul/22/remove-encoding-python/</id><summary type="html">&lt;p&gt;Lors du passage à python 3 sur un projet, j'ai décidé de supprimer les lignes
qui donnent l'encodage du fichier. En effet, ils étaient tous en UTF-8 et c'est
l'encodage par défaut sous python 3.&lt;/p&gt;
&lt;p&gt;J'ai écrit ce petit script pour automatiser tout ça :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="k"&gt;$(&lt;/span&gt;find chsdi/ -name …&lt;/pre&gt;</summary><content type="html">&lt;p&gt;Lors du passage à python 3 sur un projet, j'ai décidé de supprimer les lignes
qui donnent l'encodage du fichier. En effet, ils étaient tous en UTF-8 et c'est
l'encodage par défaut sous python 3.&lt;/p&gt;
&lt;p&gt;J'ai écrit ce petit script pour automatiser tout ça :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="k"&gt;$(&lt;/span&gt;find chsdi/ -name &lt;span class="se"&gt;\*&lt;/span&gt;.py&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Remove coding line
&lt;/span&gt;  sed -i &lt;span class="s1"&gt;'/^# *-\*- .*coding: utf-8 -\*-/d'&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
  &lt;span class="c1"&gt;# Remove whitespace line after it if it exists
&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; head -n &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;'^$'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    sed -i &lt;span class="s1"&gt;'1d'&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="python"></category><category term="Bash/Shell"></category></entry><entry><title>Move line matching a regexp in bash</title><link href="//www.jujens.eu/posts/en/2015/Jul/22/move-lines-matching-pattern-bash/" rel="alternate"></link><published>2015-07-22T00:00:00+02:00</published><updated>2015-07-22T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-07-22:/posts/en/2015/Jul/22/move-lines-matching-pattern-bash/</id><summary type="html">&lt;p&gt;Recently I had to update the &lt;a class="reference external" href="https://github.com/google/closure-compiler"&gt;closure compiler&lt;/a&gt; on a project. To do so, I had to
move some code lines used by closure: the compiler uses &lt;tt class="docutils literal"&gt;goog.require&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;goog.provide&lt;/tt&gt; to manage dependencies. In the version used by the project,
these lines were in an IEF:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;goog …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;Recently I had to update the &lt;a class="reference external" href="https://github.com/google/closure-compiler"&gt;closure compiler&lt;/a&gt; on a project. To do so, I had to
move some code lines used by closure: the compiler uses &lt;tt class="docutils literal"&gt;goog.require&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;goog.provide&lt;/tt&gt; to manage dependencies. In the version used by the project,
these lines were in an IEF:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'toto'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'titi'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;But this way to write code is not possible any more with newer versions of the
closure compiler: dependencies must be managed at file level. &lt;tt class="docutils literal"&gt;goog.require&lt;/tt&gt;
and &lt;tt class="docutils literal"&gt;goog.provide&lt;/tt&gt; must be moved out of the IEF. Since lost of files were to
be updated, I wrote the following script to automate the process.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Loop&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;have&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;IEF&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="nx"&gt;folder&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;grep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rl&lt;/span&gt; &lt;span class="s1"&gt;'^(function() {'&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;grep&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Remove&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;IEF&lt;/span&gt;
    &lt;span class="nx"&gt;sed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="s1"&gt;'/^(function() {/d'&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}&amp;quot;&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Remove&lt;/span&gt; &lt;span class="nx"&gt;goog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;indent&lt;/span&gt;
    &lt;span class="nx"&gt;sed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="s1"&gt;'s/^  (goog.(provide|require))/\1/g'&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}&amp;quot;&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Print&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;bottom&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;For&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;fist&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="nx"&gt;concerning&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt; &lt;span class="nx"&gt;management&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;we&lt;/span&gt; &lt;span class="nx"&gt;print&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;IEF&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;we&lt;/span&gt; &lt;span class="nx"&gt;print&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Reverse&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;again&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;tac&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'/goog.(provide|require)/ &amp;amp;&amp;amp; ! seen {print &amp;quot;(function() {&amp;quot;; seen=1} {print}'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;tac&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}.new&amp;quot;&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;We&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;because&lt;/span&gt; &lt;span class="nx"&gt;due&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;pipes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="nx"&gt;may&lt;/span&gt; &lt;span class="nx"&gt;get&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;written&lt;/span&gt; &lt;span class="nx"&gt;before&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;completely&lt;/span&gt; &lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;That&lt;/span&gt; &lt;span class="nx"&gt;will&lt;/span&gt; &lt;span class="nx"&gt;prevent&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;work&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;mv&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}.new&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;${file}&amp;quot;&lt;/span&gt;
&lt;span class="nx"&gt;done&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Bash/Shell"></category></entry><entry><title>Remove the encoding line in python files</title><link href="//www.jujens.eu/posts/en/2015/Jul/22/remove-encoding-python/" rel="alternate"></link><published>2015-07-22T00:00:00+02:00</published><updated>2015-07-22T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-07-22:/posts/en/2015/Jul/22/remove-encoding-python/</id><summary type="html">&lt;p&gt;When making a python project python 3 only, I decided to delete the lines giving
the encoding of the files. All files were in UTF-8 and it is the default
encoding in python 3.&lt;/p&gt;
&lt;p&gt;I wrote this little script to get the job done.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="k"&gt;$(&lt;/span&gt;find chsdi/ -name …&lt;/pre&gt;</summary><content type="html">&lt;p&gt;When making a python project python 3 only, I decided to delete the lines giving
the encoding of the files. All files were in UTF-8 and it is the default
encoding in python 3.&lt;/p&gt;
&lt;p&gt;I wrote this little script to get the job done.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="k"&gt;$(&lt;/span&gt;find chsdi/ -name &lt;span class="se"&gt;\*&lt;/span&gt;.py&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Remove coding line
&lt;/span&gt;  sed -i &lt;span class="s1"&gt;'/^# *-\*- .*coding: utf-8 -\*-/d'&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
  &lt;span class="c1"&gt;# Remove whitespace line after it if it exists
&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt; head -n &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s1"&gt;'^$'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    sed -i &lt;span class="s1"&gt;'1d'&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="python"></category><category term="Bash/Shell"></category></entry><entry><title>CORS and HTTP authentication</title><link href="//www.jujens.eu/posts/en/2015/Jun/27/webdav-options/" rel="alternate"></link><published>2015-06-27T00:00:00+02:00</published><updated>2015-06-27T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-06-27:/posts/en/2015/Jun/27/webdav-options/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#nginx" id="id1"&gt;Nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#apache" id="id2"&gt;Apache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#javascript" id="id3"&gt;Javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#see-also" id="id4"&gt;See also&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Before doing a request (POST, GET, PUT, …) on another domain with Javascript,
web browsers will perform an OPTIONS request to verify that the request is
likely to be accepted by the server. They mostly check for CORS headers.&lt;/p&gt;
&lt;p&gt;This doesn't cause any troubles if …&lt;/p&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#nginx" id="id1"&gt;Nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#apache" id="id2"&gt;Apache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#javascript" id="id3"&gt;Javascript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#see-also" id="id4"&gt;See also&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Before doing a request (POST, GET, PUT, …) on another domain with Javascript,
web browsers will perform an OPTIONS request to verify that the request is
likely to be accepted by the server. They mostly check for CORS headers.&lt;/p&gt;
&lt;p&gt;This doesn't cause any troubles if your service doesn't require authentication:
the OPTIONS request is performed without the authentication headers. So, for
instance, if you are trying to connect to an owncloud instance with the webdav
protocol, the OPTIONS request will failed due to a 401 unauthorized error.&lt;/p&gt;
&lt;p&gt;To avoid that, you must make sure that when requested with the OPTIONS method,
the endpoint always respond with a 200 status code and with the proper header
even without authentication. You can either do it programmatically in the code
of your application or with your web server configuration.&lt;/p&gt;
&lt;p&gt;I provide the correct configuration sample for nginx and apache. You should be
able to adapt them for other web server or for your favorite programming
language. Both include the headers and how to return the 200 status code on
options. I also provide a sample JS code that can make the request.&lt;/p&gt;
&lt;div class="section" id="nginx"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Nginx&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;'Access-Control-Allow-Methods'&lt;/span&gt; &lt;span class="s"&gt;'GET,OPTIONS,PUT,DELETE'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;'Access-Control-Allow-Credentials'&lt;/span&gt; &lt;span class="s"&gt;'true'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;'Access-Control-Allow-Origin'&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="nv"&gt;$http_origin'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;'Access-Control-Allow-Headers'&lt;/span&gt; &lt;span class="s"&gt;'Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request_method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;OPTIONS&lt;/span&gt; &lt;span class="s"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You may also need to add the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Access-Control-Expose-Headers&lt;/span&gt;&lt;/tt&gt; to allow the browser to export the headers. This will be required to use them from AngularJS for instance:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;'Access-Control-Expose-Headers'&lt;/span&gt; &lt;span class="s"&gt;'Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With,Content-Disposition'&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="apache"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Apache&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="nb"&gt;Header&lt;/span&gt; always set Access-Control-Allow-Origin &lt;span class="s2"&gt;&amp;quot;http://waffle&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;Header&lt;/span&gt; always set Access-Control-Allow-Methods &lt;span class="s2"&gt;&amp;quot;POST, GET, OPTIONS&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;Header&lt;/span&gt; always set Access-Control-Allow-Credentials &lt;span class="s2"&gt;&amp;quot;true&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;Header&lt;/span&gt; always set Access-Control-Allow-Headers &lt;span class="s2"&gt;&amp;quot;Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;RewriteCond&lt;/span&gt; %{REQUEST_METHOD} OPTIONS
&lt;span class="nb"&gt;RewriteRule&lt;/span&gt; ^(.*)$ $1 [R=200,L]
&lt;/pre&gt;
&lt;p&gt;If you need &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;/tt&gt; to be exactly the domain from the origin header, you can use:&lt;/p&gt;
&lt;pre class="code apache literal-block"&gt;
&lt;span class="nb"&gt;SetEnvIf&lt;/span&gt; Origin &lt;span class="s2"&gt;&amp;quot;http(s)?://(.+)$&amp;quot;&lt;/span&gt; CORS=$0
&lt;span class="nb"&gt;Header&lt;/span&gt; always set Access-Control-Allow-Origin %{CORS}e env=CORS
&lt;/pre&gt;
&lt;p&gt;You may also need to add the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Access-Control-Expose-Headers&lt;/span&gt;&lt;/tt&gt; to allow the browser to export the headers. This will be required to use them from AngularJS for instance:&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;Header&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt; &lt;span class="s"&gt;set&lt;/span&gt; &lt;span class="s"&gt;Access-Control-Expose-Headers&lt;/span&gt; &lt;span class="s"&gt;'Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With,Content-Disposition'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="javascript"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Javascript&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your javascript code must supply the &lt;tt class="docutils literal"&gt;Authorization&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Content-Type&lt;/span&gt;&lt;/tt&gt;
headers. For instance, with the angular framework:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;webdav&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;withCredentials&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Authorization&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Basic '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'application/vnd.google-earth.kml+xml; charset=utf-8'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getKml&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="see-also"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;See also&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This answer on stackoverflow: &lt;a class="reference external" href="http://stackoverflow.com/questions/21455045/angularjs-http-cors-and-http-authentication"&gt;http://stackoverflow.com/questions/21455045/angularjs-http-cors-and-http-authentication&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Auto-hébergement"></category><category term="nginx"></category><category term="apache"></category><category term="webdav"></category><category term="owncloud"></category></entry><entry><title>Use udev to setfacl when mounting a usb drive</title><link href="//www.jujens.eu/posts/en/2015/May/31/udev-setfacl/" rel="alternate"></link><published>2015-05-31T00:00:00+02:00</published><updated>2015-05-31T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-05-31:/posts/en/2015/May/31/udev-setfacl/</id><content type="html">&lt;p&gt;Write the line below (and adapt it) in &lt;tt class="docutils literal"&gt;/etc/udev/rules.d/&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
SUBSYSTEMS==&amp;quot;block&amp;quot;,ACTION==&amp;quot;add&amp;quot;,KERNEL==&amp;quot;sd?1&amp;quot;,RUN+=&amp;quot;/usr/bin/setfacl -m    u:apache:r-x /run/media/jenselme&amp;quot;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Attention:&lt;/strong&gt; if the path of the command is not absolute, udev will search of
it in &lt;tt class="docutils literal"&gt;/usr/lib/udev&lt;/tt&gt;.&lt;/p&gt;
</content><category term="Trucs et astuces"></category></entry><entry><title>Use docker to deploy a Glassfish application</title><link href="//www.jujens.eu/posts/en/2015/May/24/deploy-glassfish-docker/" rel="alternate"></link><published>2015-05-24T00:00:00+02:00</published><updated>2015-05-24T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-05-24:/posts/en/2015/May/24/deploy-glassfish-docker/</id><summary type="html">&lt;p&gt;Recently I had to deploy an application on Glassfish. Since Glassfish is not
packaged on the distribution I have on my server (Fedora Server) and I wanted to
avoid to pollute my system I decided to use Docker.&lt;/p&gt;
&lt;p&gt;In order to deploy my application correctly, I based my Dockerfile on …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently I had to deploy an application on Glassfish. Since Glassfish is not
packaged on the distribution I have on my server (Fedora Server) and I wanted to
avoid to pollute my system I decided to use Docker.&lt;/p&gt;
&lt;p&gt;In order to deploy my application correctly, I based my Dockerfile on the
latest official image of glassfish from the docker hub. This image is based on
debian and it supports java 8 (there is another image which support java 7).&lt;/p&gt;
&lt;p&gt;Nothing fancy in the dockerfile. I copy the the war file in the container and
set the entry points to a custom script. This script will start Glassfish,
deploy the application and then restart the server in verbose mode.&lt;/p&gt;
&lt;pre class="code docker literal-block"&gt;
&lt;span class="c"&gt;## -*- docker-image-name: &amp;quot;aot-java&amp;quot; -*-&lt;/span&gt;
&lt;span class="c"&gt;# AoT&lt;/span&gt;
&lt;span class="c"&gt;#&lt;/span&gt;
&lt;span class="c"&gt;# Version 1&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="s"&gt;glassfish:latest&lt;/span&gt;

&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; Jujens &amp;quot;jujens&amp;#64;jujens.eu&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt; aot.war /
&lt;span class="k"&gt;COPY&lt;/span&gt; start.sh /

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/start.sh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Why didn't I just deploy the application in the dockerfile? In order to deploy
the app, Glassfish must be running. If we used the following code to deploy the
application, what would have happened?&lt;/p&gt;
&lt;pre class="code docker literal-block"&gt;
&lt;span class="k"&gt;RUN&lt;/span&gt; /usr/local/glassfish4/bin/asadmin start-domain
&lt;span class="k"&gt;RUN&lt;/span&gt; /usr/local/glassfish4/bin/asadmin -u admin deploy /aot.war
&lt;/pre&gt;
&lt;p&gt;Docker create a temporary container and launch the command in it. Once the
server has started, the command will exit and the container will stop. Then
docker will create a new temporary container and launch
&lt;tt class="docutils literal"&gt;/usr/local/glassfish4/bin/asadmin &lt;span class="pre"&gt;-u&lt;/span&gt; admin deploy /aot.war&lt;/tt&gt; in it. But since
the first container is stopped, Glassfish is not running any more. So the deploy
command fails.&lt;/p&gt;
&lt;p&gt;If we started the server with &lt;tt class="docutils literal"&gt;/usr/local/glassfish4/bin/asadmin &lt;span class="pre"&gt;start-domain&lt;/span&gt;
&lt;span class="pre"&gt;--verbose&lt;/span&gt;&lt;/tt&gt;, the command would never have exited and docker would have been
stuck.&lt;/p&gt;
&lt;p&gt;So the solution is to use a custom script as entry point which will:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Start the server&lt;/li&gt;
&lt;li&gt;Deploy the application&lt;/li&gt;
&lt;li&gt;Stop the server&lt;/li&gt;
&lt;li&gt;Restart it in verbose mode so this command doesn't exit and the container
doesn't stop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can then run the container with: &lt;tt class="docutils literal"&gt;docker run &lt;span class="pre"&gt;--name&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;container-name&amp;gt;&lt;/span&gt; &lt;span class="pre"&gt;-d&lt;/span&gt; &lt;span class="pre"&gt;-p&lt;/span&gt;
8080:8080 &lt;span class="pre"&gt;&amp;lt;image-name&amp;gt;&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Here is the script:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/bin/sh
&lt;/span&gt;
/usr/local/glassfish4/bin/asadmin start-domain
/usr/local/glassfish4/bin/asadmin -u admin deploy /aot.war
/usr/local/glassfish4/bin/asadmin stop-domain
/usr/local/glassfish4/bin/asadmin start-domain --verbose
&lt;/pre&gt;
&lt;p&gt;Another solution would have been to simply use the default image, launch a
container from it, connect to it with &lt;a class="reference external" href="/posts/2015/Mar/25/connect-docker/"&gt;nsenter&lt;/a&gt; and deploy the war from there. But I find
this method quite tricky and you have to use docker in a way that was never
intended.&lt;/p&gt;
</content><category term="Programmation"></category><category term="Java"></category><category term="Glassfish"></category><category term="Docker"></category></entry><entry><title>Docker tips</title><link href="//www.jujens.eu/posts/2015/May/24/docker/" rel="alternate"></link><published>2015-05-24T00:00:00+02:00</published><updated>2015-05-24T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-05-24:/posts/2015/May/24/docker/</id><summary type="html">&lt;p&gt;For my tips about docker compose, go &lt;a class="reference external" href="//www.jujens.eu/posts/2017/Jun/11/docker-compose/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-an-image" id="id1"&gt;Create an image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#save-and-import" id="id2"&gt;Save and import&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#run" id="id3"&gt;Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#volumes" id="id4"&gt;Volumes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#networking" id="id5"&gt;Networking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#attach-to-a-running-container" id="id6"&gt;Attach to a running container&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-customs-dns" id="id7"&gt;Use customs DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#usage-with-sudo" id="id8"&gt;Usage with sudo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="create-an-image"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Create an image&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker build -t &amp;lt;name&amp;gt; .
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="save-and-import"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Save and import&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker save &amp;lt;image&amp;gt; &amp;gt; file
docker load &amp;lt; &amp;lt;image&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="run"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Run&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker run --name …&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;For my tips about docker compose, go &lt;a class="reference external" href="//www.jujens.eu/posts/2017/Jun/11/docker-compose/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#create-an-image" id="id1"&gt;Create an image&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#save-and-import" id="id2"&gt;Save and import&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#run" id="id3"&gt;Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#volumes" id="id4"&gt;Volumes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#networking" id="id5"&gt;Networking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#attach-to-a-running-container" id="id6"&gt;Attach to a running container&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#use-customs-dns" id="id7"&gt;Use customs DNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#usage-with-sudo" id="id8"&gt;Usage with sudo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="create-an-image"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Create an image&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker build -t &amp;lt;name&amp;gt; .
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="save-and-import"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Save and import&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker save &amp;lt;image&amp;gt; &amp;gt; file
docker load &amp;lt; &amp;lt;image&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="run"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Run&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker run --name aot -d -p 8080:8080 --link redis:redis aot
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="volumes"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Volumes&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
docker run -it --rm -v $(pwd)/test:/root busybox /bin/sh
&lt;/pre&gt;
&lt;p&gt;If SELinux is enabled, use: &lt;tt class="docutils literal"&gt;Z&lt;/tt&gt; (capital z, recommended, better matches the context of the container, eg &lt;tt class="docutils literal"&gt;system_u:object_r:container_file_t:s0:c667,c788&lt;/tt&gt; with the &lt;tt class="docutils literal"&gt;c667,c788&lt;/tt&gt; part changing for each container) or &lt;tt class="docutils literal"&gt;z&lt;/tt&gt; (lower caps z to have a context appliable to all containers, eg &lt;tt class="docutils literal"&gt;system_u:object_r:container_file_t:s0&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
docker run -it --rm -v $(pwd)/test:/root:Z busybox /bin/sh
&lt;/pre&gt;
&lt;p&gt;If you cannot run with &lt;tt class="docutils literal"&gt;Z&lt;/tt&gt;, run &lt;tt class="docutils literal"&gt;chcon &lt;span class="pre"&gt;-R&lt;/span&gt; system_u:object_r:container_file_t:s0 FOLDER&lt;/tt&gt;. If you must use a different context on your system, start a container with a volume mounted with &lt;tt class="docutils literal"&gt;z&lt;/tt&gt; (lower caps z indented) and run &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-dZ&lt;/span&gt; FOLDER&lt;/tt&gt; to get the proper context.&lt;/p&gt;
&lt;p&gt;See &lt;a class="reference external" href="https://blog.voina.org/docker-selinux/"&gt;https://blog.voina.org/docker-selinux/&lt;/a&gt;, &lt;a class="reference external" href="http://www.projectatomic.io/blog/2015/06/using-volumes-with-docker-can-cause-problems-with-selinux/"&gt;http://www.projectatomic.io/blog/2015/06/using-volumes-with-docker-can-cause-problems-with-selinux/&lt;/a&gt; and &lt;a class="reference external" href="https://opensource.com/business/14/9/security-for-docker"&gt;https://opensource.com/business/14/9/security-for-docker&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also use multiple mount options by separating them with a comma. For instance to mount a read only file with SELinux support, you can do this:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
docker run -it --rm -v $(pwd)/test/README.rst:/root/README.rst:ro,Z busybox /bin/sh
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="networking"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Networking&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have SELinux enabled and use user namespaces, you will hit two SELinux errors related to ip tables:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
avc:  denied  { net_admin } for  pid=7464 comm=&amp;quot;iptables&amp;quot; capability=12  scontext=system_u:system_r:iptables_t:s0 tcontext=system_u:system_r:iptables_t:s0 tclass=cap_userns permissive=1
avc:  denied  { net_raw } for  pid=8158 comm=&amp;quot;iptables&amp;quot; capability=13  scontext=system_u:system_r:iptables_t:s0 tcontext=system_u:system_r:iptables_t:s0 tclass=cap_userns permissive=0
&lt;/pre&gt;
&lt;p&gt;To allow these actions in SELinux, run as root (the plain text description of the rule is avaiable in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;dk-userns-iptables.te&lt;/span&gt;&lt;/tt&gt;):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
ausearch -c 'iptables' --raw | audit2allow -M dk-userns-iptables
semodule -X 300 -i dk-userns-iptables.pp
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="attach-to-a-running-container"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Attach to a running container&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are running docker 1.3 or above, you should use: &lt;tt class="docutils literal"&gt;docker exec &lt;span class="pre"&gt;-it&lt;/span&gt; CONTAINER COMMAND&lt;/tt&gt; to run &lt;tt class="docutils literal"&gt;COMMAND&lt;/tt&gt; within the container. You can easily create a function to ease the thing and run bash by default:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
dk-enter&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;/bin/bash&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You can easily open a shell in a running docker container with the following
commands:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Get the container pid: &lt;tt class="docutils literal"&gt;docker inspect &lt;span class="pre"&gt;-f&lt;/span&gt; &lt;span class="pre"&gt;{{.State.Pid}}&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;container-id&amp;gt;&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Connect: &lt;tt class="docutils literal"&gt;nsenter &lt;span class="pre"&gt;--target&lt;/span&gt; &amp;lt;pid&amp;gt; &lt;span class="pre"&gt;--mount&lt;/span&gt; &lt;span class="pre"&gt;--uts&lt;/span&gt; &lt;span class="pre"&gt;--ipc&lt;/span&gt; &lt;span class="pre"&gt;--net&lt;/span&gt; &lt;span class="pre"&gt;--pid&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="use-customs-dns"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Use customs DNS&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;During development you may need to use custom domains to reach your site. Since these domains aren't real and must point to your machine, you need to use a custom DNS resolver. I'll detail here, how to acheive this with &lt;tt class="docutils literal"&gt;dnsmaq&lt;/tt&gt; and Network Manager.&lt;/p&gt;
&lt;p&gt;First, you need to install &lt;tt class="docutils literal"&gt;dnsmaq&lt;/tt&gt;. It should be in the repositories of your distribution.&lt;/p&gt;
&lt;p&gt;Then you need to map your domains to the proper ip addresses. To do that, create as root &lt;tt class="docutils literal"&gt;/etc/NetworkManager/dnsmasq.d/mapping.conf&lt;/tt&gt; and add something like this to map the domain to the ip:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
address=/dev.here/127.0.0.1
&lt;/pre&gt;
&lt;p&gt;Now, as described &lt;a class="reference external" href="https://github.com/moby/moby/issues/23910#issuecomment-271353348"&gt;here&lt;/a&gt; you need to configure Network Manager to listen to the docker bridge, so the DNS requests from your containers are correctly passed to dnsmasq. To do so, create &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/NetworkManager/dnsmasq.d/docker-bridge.conf&lt;/span&gt;&lt;/tt&gt; with this content (if you use another ip than the default one, you will have to adapt this):&lt;/p&gt;
&lt;pre class="literal-block"&gt;
listen-address=172.17.0.1
&lt;/pre&gt;
&lt;p&gt;Restart Network Manager for the changes to be taken into account: &lt;tt class="docutils literal"&gt;systemctl restart NetworkManager&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Then, as described &lt;a class="reference external" href="https://github.com/moby/moby/issues/23910#issuecomment-271351277"&gt;here&lt;/a&gt;, we need to configure the docker daemon to use our DNS. To to that, create &lt;tt class="docutils literal"&gt;/etc/docker/daemon.json&lt;/tt&gt; with this content (or add the &lt;tt class="docutils literal"&gt;dns&lt;/tt&gt; entry if the file already exists):&lt;/p&gt;
&lt;pre class="code json literal-block"&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;quot;dns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;172.17.0.1&amp;quot;&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Restart docker for the changes to be taken into account: &lt;tt class="docutils literal"&gt;systemctl restart docker&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Finally, you need to allow DNS requests in your firewall (the commands below are for firewalld, default firewall on Fedora):&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Allow permanently the DNS service in the firewall (remove &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--permanent&lt;/span&gt;&lt;/tt&gt; and don't run the second command to make this temporary): &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;firewall-cmd&lt;/span&gt; &lt;span class="pre"&gt;--add-service=dns&lt;/span&gt; &lt;span class="pre"&gt;--permanent&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Reload the configuration: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;firewall-cmd&lt;/span&gt; &lt;span class="pre"&gt;--reload&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="usage-with-sudo"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id8"&gt;Usage with sudo&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want your users to use the docker command but want to prevent some options, you should rely on sudo to allow your users to run &lt;tt class="docutils literal"&gt;sudo docker SOMETING&lt;/tt&gt;. You can then configure sudo to prevent some action. Here is an example that allows user &lt;tt class="docutils literal"&gt;jenselme&lt;/tt&gt; to run &lt;tt class="docutils literal"&gt;sudo docker&lt;/tt&gt; without a password without allowing the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--privileged&lt;/span&gt;&lt;/tt&gt; option nor to disable namespaces:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
jenselme ALL=(root) NOPASSWD: /usr/bin/docker,
    ! /usr/bin/docker *--privileged*,
    ! /usr/bin/docker *=host*
&lt;/pre&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Docker"></category></entry><entry><title>AngularJS tips</title><link href="//www.jujens.eu/posts/en/2015/Apr/26/angularjs-tips/" rel="alternate"></link><published>2015-04-26T00:00:00+02:00</published><updated>2015-04-26T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-04-26:/posts/en/2015/Apr/26/angularjs-tips/</id><summary type="html">&lt;p&gt;This page lists all the angularjs tips I have collected.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#disable-http-request-caching" id="id1"&gt;Disable HTTP request caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#launch-an-action-after-a-digest" id="id2"&gt;Launch an action after a $digest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#download-binary-data" id="id3"&gt;Download binary data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#debugging" id="id4"&gt;Debugging&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#get-the-scope" id="id5"&gt;Get the scope&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#get-a-service" id="id6"&gt;Get a service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="disable-http-request-caching"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Disable HTTP request caching&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is mostly useful on Internet Explorer: every HTTP requests made with the &lt;tt class="docutils literal"&gt;$http&lt;/tt&gt; service …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;This page lists all the angularjs tips I have collected.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#disable-http-request-caching" id="id1"&gt;Disable HTTP request caching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#launch-an-action-after-a-digest" id="id2"&gt;Launch an action after a $digest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#download-binary-data" id="id3"&gt;Download binary data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#debugging" id="id4"&gt;Debugging&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#get-the-scope" id="id5"&gt;Get the scope&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#get-a-service" id="id6"&gt;Get a service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="disable-http-request-caching"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Disable HTTP request caching&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is mostly useful on Internet Explorer: every HTTP requests made with the &lt;tt class="docutils literal"&gt;$http&lt;/tt&gt; service will be cached by the browser. This means that if a resource changed on the server, refetching it, by default, will not show the modification to the client. The application will be presented the request from the cache of the browser. To prevent that, we disable the cache for HTTP requests.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$httpProvider&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Disable caching for Internet Explorer.
&lt;/span&gt;        &lt;span class="c1"&gt;// See: http://stackoverflow.com/a/19771501
&lt;/span&gt;        &lt;span class="nx"&gt;$httpProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$httpProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;$httpProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Disable IE ajax request caching
&lt;/span&gt;        &lt;span class="nx"&gt;$httpProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'If-Modified-Since'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="launch-an-action-after-a-digest"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Launch an action after a $digest&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use &lt;tt class="docutils literal"&gt;$timeout&lt;/tt&gt; with only one parameter:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;$timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;do_after_digest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="download-binary-data"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Download binary data&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You must set &lt;tt class="docutils literal"&gt;responseType&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;'arraybuffer'&lt;/tt&gt; in the options of the requests, like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'your/webservice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//this is your json data string
&lt;/span&gt;        &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s1"&gt;'Content-type'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'application/json'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;responseType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'arraybuffer'&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;objectUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objectUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//upload failed
&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Cf : &lt;a class="reference external" href="http://stackoverflow.com/a/22448640"&gt;http://stackoverflow.com/a/22448640&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="debugging"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Debugging&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Note: &lt;tt class="docutils literal"&gt;$0&lt;/tt&gt; refers to the last selected element by the debug tool. Works at
least on Firefox and Chrome. In all these examples, this element must be under
the controller.&lt;/p&gt;
&lt;div class="section" id="get-the-scope"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Get the scope&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="get-a-service"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Get a service&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;myService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;injector&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'myService'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category><category term="AngularJS"></category></entry><entry><title>Git tips</title><link href="//www.jujens.eu/posts/en/2015/Apr/26/gittips/" rel="alternate"></link><published>2015-04-26T00:00:00+02:00</published><updated>2015-04-26T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-04-26:/posts/en/2015/Apr/26/gittips/</id><summary type="html">&lt;p&gt;This pages provides all gitips I have collected.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#rebase" id="id1"&gt;Rebase&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#split-commit" id="id2"&gt;Split commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#autosquash" id="id3"&gt;Autosquash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#cancel-file-deletion" id="id4"&gt;Cancel file deletion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#patch" id="id5"&gt;Patch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#branches" id="id6"&gt;Branches&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#ignoring-versioned-files" id="id7"&gt;Ignoring versioned files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#permanently-remove-files-or-folder-from-repo" id="id8"&gt;Permanently remove files or folder from repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#run-multiple-hooks-in-parallel" id="id9"&gt;Run multiple hooks in parallel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#revert-a-merge-commit" id="id10"&gt;Revert a merge commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="rebase"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Rebase&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="split-commit"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id2"&gt;Split commit&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After &lt;tt class="docutils literal"&gt;git rebase &lt;span class="pre"&gt;-i&lt;/span&gt;&lt;/tt&gt;, run &lt;tt class="docutils literal"&gt;git reset HEAD~&lt;/tt&gt; to split …&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;This pages provides all gitips I have collected.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#rebase" id="id1"&gt;Rebase&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#split-commit" id="id2"&gt;Split commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#autosquash" id="id3"&gt;Autosquash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#cancel-file-deletion" id="id4"&gt;Cancel file deletion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#patch" id="id5"&gt;Patch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#branches" id="id6"&gt;Branches&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#ignoring-versioned-files" id="id7"&gt;Ignoring versioned files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#permanently-remove-files-or-folder-from-repo" id="id8"&gt;Permanently remove files or folder from repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#run-multiple-hooks-in-parallel" id="id9"&gt;Run multiple hooks in parallel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#revert-a-merge-commit" id="id10"&gt;Revert a merge commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="rebase"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Rebase&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="split-commit"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id2"&gt;Split commit&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After &lt;tt class="docutils literal"&gt;git rebase &lt;span class="pre"&gt;-i&lt;/span&gt;&lt;/tt&gt;, run &lt;tt class="docutils literal"&gt;git reset HEAD~&lt;/tt&gt; to split current
commit.&lt;/p&gt;
&lt;p&gt;To split 3rd most recent commit, &lt;tt class="docutils literal"&gt;git rebase &lt;span class="pre"&gt;-i&lt;/span&gt; HEAD~3&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="autosquash"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Autosquash&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can auto-squash all commits you made to correct a previous commit with:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Create a fixup commit: &lt;tt class="docutils literal"&gt;git commit &lt;span class="pre"&gt;--fixup=COMMIT_HASH&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;tt class="docutils literal"&gt;rebase &lt;span class="pre"&gt;--interactive&lt;/span&gt; &lt;span class="pre"&gt;--autosquash&lt;/span&gt; REF&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="cancel-file-deletion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Cancel file deletion&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="literal-block"&gt;
touch &amp;lt;filename&amp;gt;
git checkout &amp;lt;filename&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="patch"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Patch&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Create a patch: &lt;tt class="docutils literal"&gt;git &lt;span class="pre"&gt;format-patch&lt;/span&gt; &lt;span class="pre"&gt;-1&lt;/span&gt; &amp;lt;commit&amp;gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Apply as patch &lt;tt class="docutils literal"&gt;git apply &amp;lt;patch&amp;gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Apply as commit: &lt;tt class="docutils literal"&gt;git am &amp;lt;patch&amp;gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="branches"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Branches&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Delete a local branch: &lt;tt class="docutils literal"&gt;git branch &lt;span class="pre"&gt;-d&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;branch-name&amp;gt;&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Delete a local branch with unmerge work:
&lt;tt class="docutils literal"&gt;git branch &lt;span class="pre"&gt;-D&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;branch-name&amp;gt;&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Delete a branch on the server:
&lt;tt class="docutils literal"&gt;git push origin &lt;span class="pre"&gt;--delete&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;branch-name&amp;gt;&lt;/span&gt;&lt;/tt&gt; or
&lt;tt class="docutils literal"&gt;git push origin :branchname&lt;/tt&gt; on old version of git&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="ignoring-versioned-files"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Ignoring versioned files&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Run &lt;tt class="docutils literal"&gt;git &lt;span class="pre"&gt;update-index&lt;/span&gt; &lt;span class="pre"&gt;--assume-unchanged&lt;/span&gt; path/to/file.txt&lt;/tt&gt; To cancel the operation, run: &lt;tt class="docutils literal"&gt;git &lt;span class="pre"&gt;update-index&lt;/span&gt; &lt;span class="pre"&gt;--no-assume-unchanged&lt;/span&gt; path/to/file.txt&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;tt class="docutils literal"&gt;git stash&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;git checkout .&lt;/tt&gt; will have an effect on the file.&lt;/p&gt;
&lt;p&gt;Source: &lt;a class="reference external" href="https://stackoverflow.com/questions/18276951/how-do-i-stop-git-from-tracking-any-changes-to-a-file-from-this-commit-forward/18277622#18277622"&gt;https://stackoverflow.com/questions/18276951/how-do-i-stop-git-from-tracking-any-changes-to-a-file-from-this-commit-forward/18277622#18277622&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="permanently-remove-files-or-folder-from-repo"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id8"&gt;Permanently remove files or folder from repo&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is an potentially dangerous command as it rewrites the history. It can
discard commits if you have shared your code with other. Use carefully. You will
need to use &lt;tt class="docutils literal"&gt;git push &lt;span class="pre"&gt;-f&lt;/span&gt;&lt;/tt&gt; to update any distant repo.&lt;/p&gt;
&lt;p&gt;It also implies that if you are working on a forked repository (on github for
instance) you won't be able to make pull requests any more as all the rewritten
commits will be included in it (that can amount to several hundreds) and it is
most likely that upstream won't want them.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git filter-branch -f --prune-empty --index-filter 'git rm -r --cached --ignore-unmatch src/main/webapp/inc/img'  -- HEAD
&lt;/pre&gt;
&lt;p&gt;With:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--ignore-unmatch&lt;/span&gt;&lt;/tt&gt; allows you to ignore nonexistent files&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-r&lt;/span&gt;&lt;/tt&gt; to delete recursively&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--prune-empty&lt;/span&gt;&lt;/tt&gt; to discard empty commit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you use a commit range (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;hash1..ref&lt;/span&gt;&lt;/tt&gt;):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the first commit is not filtered&lt;/li&gt;
&lt;li&gt;the end of the range must be a reference (a branch name for instance). You can
try to use an temporary branch as describe &lt;a class="reference external" href="http://stackoverflow.com/questions/15250070/running-filter-branch-over-a-range-of-commits"&gt;here&lt;/a&gt;
if needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you messed up, you can use the reflog to reset your repo until you run the
following commands. You must then remove the backup and force garbage collection
to regain your disk size:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
rm -rf .git/refs/original
git reflog expire --all --expire=now
git gc --prune=now --aggressive
&lt;/pre&gt;
&lt;p&gt;Normally, after a &lt;tt class="docutils literal"&gt;git push &lt;span class="pre"&gt;-f&lt;/span&gt;&lt;/tt&gt; you should see the reclaimed space. You can
also manually update the remote tracked branch by using something like
&lt;tt class="docutils literal"&gt;origin/master&lt;/tt&gt; as reference.&lt;/p&gt;
&lt;p&gt;You can add the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--all&lt;/span&gt;&lt;/tt&gt; option to rewrite all branches and tags:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch src/main/webapp/inc/img' -- --all
&lt;/pre&gt;
&lt;p&gt;If you use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--tree-filter&lt;/span&gt;&lt;/tt&gt; with the command &lt;tt class="docutils literal"&gt;rm &lt;span class="pre"&gt;-rf&lt;/span&gt;&lt;/tt&gt; instead of
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--index-filter&lt;/span&gt;&lt;/tt&gt; you will get the result slower as it checkouts the tree.&lt;/p&gt;
&lt;p&gt;You can use this command to find big files. It lists all files with their size
for each commit in master. Then, it selects only the size and the file. Lastly,
it sorts files by size, big size first and each file is counted only once.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git ls-tree -lr master | awk '{print $4 &amp;quot; &amp;quot; $5}' | sort -unr
&lt;/pre&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html"&gt;The documentation
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;For the exact command to run garbage collection:
&lt;a class="reference external" href="http://stackoverflow.com/questions/2116778/reduce-git-repository-size"&gt;http://stackoverflow.com/questions/2116778/reduce-git-repository-size&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;For the other explanations:
&lt;a class="reference external" href="http://dalibornasevic.com/posts/2-permanently-remove-files-and-folders-from-a-git-repository"&gt;http://dalibornasevic.com/posts/2-permanently-remove-files-and-folders-from-a-git-repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="run-multiple-hooks-in-parallel"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id9"&gt;Run multiple hooks in parallel&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a class="reference external" href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks"&gt;git hooks&lt;/a&gt; are very useful because they allow you to run a script before some actions (for instance: run a linter before committing or run the tests before pushing). If the script exists with 0, the action proceeds, if not, the action is cancelled.&lt;/p&gt;
&lt;p&gt;The problem is that if you have many actions to run, it can be slow. One way to mitigate this is to run the commands of the script in parallel by terminating the line with &lt;tt class="docutils literal"&gt;&amp;amp;&lt;/tt&gt; and rely on the &lt;tt class="docutils literal"&gt;wait&lt;/tt&gt; builtin to wait for all commands to complete before continuing.&lt;/p&gt;
&lt;p&gt;You cloud launch all the commands and at the end of the script simply put &lt;tt class="docutils literal"&gt;wait&lt;/tt&gt; to wait for them but the script will always exit with the 0 status code making the hook useless.&lt;/p&gt;
&lt;p&gt;One solution, to exit with a non zero status if a command had an error to do (adapt to your needs):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/bash
&lt;/span&gt;&lt;span class="c1"&gt;# See https://stackoverflow.com/a/26504775 for some background
&lt;/span&gt;
make lint-js &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="nv"&gt;JS_LINT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

make lint-py &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="nv"&gt;PY_LINT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

pipenv run python manage.py compilemessages &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="nv"&gt;MO_LINT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_PID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;JS_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_PID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;PY_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_PID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;MO_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="nv"&gt;EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;

&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In a nutshell:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;we capture the PID of the command we just run in a variable with &lt;tt class="docutils literal"&gt;$!&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;wait for the process associated to this PID to complete with &lt;tt class="docutils literal"&gt;wait $PID&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;capture the exit code of &lt;tt class="docutils literal"&gt;wait&lt;/tt&gt; (which will match the exit code of the command) with &lt;tt class="docutils literal"&gt;$?&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;sum the code. If any of them is upper than 0, the sum will be too and we will exit with a non zero status code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem with this basic script is that you don't have access to the output of the commands. Thus, you know you have a problem but don't know which one. This can be solved by sending the output of each command into a temporary file and displaying the content of this file if the command failed:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/bash
&lt;/span&gt;&lt;span class="c1"&gt;# https://stackoverflow.com/a/26504775
&lt;/span&gt;
&lt;span class="nv"&gt;JS_LINT_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp&lt;span class="k"&gt;)&lt;/span&gt;
make lint-js &amp;gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="nv"&gt;JS_LINT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

&lt;span class="nv"&gt;PY_LINT_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp&lt;span class="k"&gt;)&lt;/span&gt;
make lint-py &amp;gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="nv"&gt;PY_LINT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

&lt;span class="nv"&gt;MO_LINT_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;mktemp&lt;span class="k"&gt;)&lt;/span&gt;
pipenv run python manage.py compilemessages &amp;gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="nv"&gt;MO_LINT_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_PID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;JS_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_PID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;PY_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_PID&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;MO_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

&lt;span class="nv"&gt;EXIT_CODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -ne &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;JS LINT OUTOUPUT&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    cat &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -ne &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;PY LINT OUTOUPUT&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    cat &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -ne &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;MO LINT OUTOUPUT&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    cat &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\n\n&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

rm &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JS_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PY_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MO_LINT_LOG&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EXIT_CODE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="revert-a-merge-commit"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id10"&gt;Revert a merge commit&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Because they have two ancestors, you can't revert merge commits with a simple &lt;tt class="docutils literal"&gt;git revert HASH&lt;/tt&gt;. You need to specify the ancestor to revert to. For instance, imagine the graph below:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
* c7545ec - Tue, 26 Mar 2019 16:52:39 +0100 (2 minutes ago)
|           Add titi - Julien Enselme
*   df849a2 - Tue, 26 Mar 2019 16:51:53 +0100 (3 minutes ago)
|\            Merge branch 'tmp' - Julien Enselme
| * a23acae - Tue, 26 Mar 2019 16:51:47 +0100 (3 minutes ago) (tmp)
|/            Add tata - Julien Enselme
* 8be0cb2 - Tue, 26 Mar 2019 16:51:34 +0100 (3 minutes ago)
|           Add toto - Julien Enselme
* 75182c4 - Tue, 26 Mar 2019 16:51:24 +0100 (3 minutes ago)
            “root” - Julien Enselme
&lt;/pre&gt;
&lt;p&gt;The merge commit (&lt;tt class="docutils literal"&gt;df849a2&lt;/tt&gt;) has two ancestors:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;a23acae&lt;/tt&gt; which comes from a feature branch.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;8be0cb2&lt;/tt&gt; which comes from the main branch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To cancel it and cancel the commits from the feature branch, run  &lt;tt class="docutils literal"&gt;git revert df849a2 &lt;span class="pre"&gt;-m&lt;/span&gt; 1&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="git"></category></entry><entry><title>Connect to a running docker container</title><link href="//www.jujens.eu/posts/2015/Mar/25/connect-docker/" rel="alternate"></link><published>2015-03-25T00:00:00+01:00</published><updated>2015-03-25T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-03-25:/posts/2015/Mar/25/connect-docker/</id><summary type="html">&lt;p&gt;If you are running docker 1.3 or above, you should use: &lt;tt class="docutils literal"&gt;docker exec &lt;span class="pre"&gt;-it&lt;/span&gt; CONTAINER COMMAND&lt;/tt&gt; to run &lt;tt class="docutils literal"&gt;COMMAND&lt;/tt&gt; within the container. You can easily create a function to ease the thing and run bash by default:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
dk-enter&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;/bin/bash&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Otherwies, you can easily …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you are running docker 1.3 or above, you should use: &lt;tt class="docutils literal"&gt;docker exec &lt;span class="pre"&gt;-it&lt;/span&gt; CONTAINER COMMAND&lt;/tt&gt; to run &lt;tt class="docutils literal"&gt;COMMAND&lt;/tt&gt; within the container. You can easily create a function to ease the thing and run bash by default:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
dk-enter&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;/bin/bash&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Otherwies, you can easily open a shell in a running docker container with the following commands:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Get the container pid: &lt;tt class="docutils literal"&gt;docker inspect &lt;span class="pre"&gt;-f&lt;/span&gt; &lt;span class="pre"&gt;{{.State.Pid}}&lt;/span&gt; &lt;span class="pre"&gt;&amp;lt;container-id&amp;gt;&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Connect: &lt;tt class="docutils literal"&gt;nsenter &lt;span class="pre"&gt;--target&lt;/span&gt; &amp;lt;pid&amp;gt; &lt;span class="pre"&gt;--mount&lt;/span&gt; &lt;span class="pre"&gt;--uts&lt;/span&gt; &lt;span class="pre"&gt;--ipc&lt;/span&gt; &lt;span class="pre"&gt;--net&lt;/span&gt; &lt;span class="pre"&gt;--pid&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Trucs et astuces"></category><category term="Docker"></category></entry><entry><title>VirtualBox</title><link href="//www.jujens.eu/posts/2015/Mar/01/virtualbox/" rel="alternate"></link><published>2015-03-01T00:00:00+01:00</published><updated>2015-03-01T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-03-01:/posts/2015/Mar/01/virtualbox/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#transform-img-disk-qemu-to-vdi-virtual-box" id="id1"&gt;Transform img disk (qemu) to vdi (Virtual Box)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#transform-vdi-to-img" id="id2"&gt;Transform vdi to img&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#compress-an-image" id="id3"&gt;Compress an image&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-windows-guest" id="id4"&gt;Prepare Windows guest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-linux-guest" id="id5"&gt;Prepare Linux guest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#compess" id="id6"&gt;Compess&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#resize-a-disk" id="id7"&gt;Resize a disk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#mount-a-vdi-to-the-local-fs" id="id8"&gt;Mount a VDI to the local FS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="transform-img-disk-qemu-to-vdi-virtual-box"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Transform img disk (qemu) to vdi (Virtual Box)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You need to convert img in raw with qemu-img …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#transform-img-disk-qemu-to-vdi-virtual-box" id="id1"&gt;Transform img disk (qemu) to vdi (Virtual Box)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#transform-vdi-to-img" id="id2"&gt;Transform vdi to img&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#compress-an-image" id="id3"&gt;Compress an image&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-windows-guest" id="id4"&gt;Prepare Windows guest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#prepare-linux-guest" id="id5"&gt;Prepare Linux guest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#compess" id="id6"&gt;Compess&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#resize-a-disk" id="id7"&gt;Resize a disk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#mount-a-vdi-to-the-local-fs" id="id8"&gt;Mount a VDI to the local FS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="transform-img-disk-qemu-to-vdi-virtual-box"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Transform img disk (qemu) to vdi (Virtual Box)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You need to convert img in raw with qemu-img and then raw to vdi. It will take time.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
$ qemu-img convert WindowsXP.img -O raw WindowsXP.raw
$ VBoxManage convertdd WindowsXP.raw &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.VirtualBox/VDI/WindowsXP.vdi
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="transform-vdi-to-img"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Transform vdi to img&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code bash literal-block"&gt;
$ VBoxManage clonehd sdb.vdi sdb.raw --format RAW
$ qemu-img convert sdb.raw -O img sdb.img
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="compress-an-image"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Compress an image&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="prepare-windows-guest"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Prepare Windows guest&lt;/a&gt;&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;run defrag in the guest (Windows)&lt;/li&gt;
&lt;li&gt;nullify free space: &lt;tt class="docutils literal"&gt;sdelete –z&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="prepare-linux-guest"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Prepare Linux guest&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code bash literal-block"&gt;
sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/bigemptyfile &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4096k
sudo rm -rf /bigemptyfile
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="compess"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Compess&lt;/a&gt;&lt;/h3&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;shutdown the guest VM&lt;/li&gt;
&lt;li&gt;Run VBoxManage's compact command: &lt;tt class="docutils literal"&gt;VBoxManage.exe modifyhd thedisk.vdi &lt;span class="pre"&gt;--compact&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="resize-a-disk"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Resize a disk&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code bash literal-block"&gt;
vboxmanage modifyhd /home/CHEMIN/VIRTUALBOX&lt;span class="se"&gt;\V&lt;/span&gt;OTRE.vdi –resize &lt;span class="m"&gt;80000&lt;/span&gt; &lt;span class="c1"&gt;# 80 Go HDD&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="mount-a-vdi-to-the-local-fs"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id8"&gt;Mount a VDI to the local FS&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Run these commands as root:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Enable the proper kernel module: &lt;tt class="docutils literal"&gt;modprobe nbd&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Create a virtual device with at &lt;tt class="docutils literal"&gt;/dev/nbd0&lt;/tt&gt; with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-nbd&lt;/span&gt; &lt;span class="pre"&gt;-c&lt;/span&gt; /dev/nbd0 /PATH/TO/YOUR/VDI/disk.vdi&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;List the partitions on the disk with &lt;tt class="docutils literal"&gt;parted /dev/nbd0 print&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Mount the partition in &lt;tt class="docutils literal"&gt;/mnt/vdi&lt;/tt&gt; (eg if you want partition 2):&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;mkdir /mnt/vdi&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;mount /dev/nbd0p2 /mnt/vdi/&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Extract the data you need by navigating under &lt;tt class="docutils literal"&gt;/mnt/vdi&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Unmount the volume: &lt;tt class="docutils literal"&gt;umount /dev/nbd0p2&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Disable the virtual drive with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;qemu-nbd&lt;/span&gt; &lt;span class="pre"&gt;--disconnect&lt;/span&gt; /dev/nbd0&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you want to mount a LVM volume, you will get an &lt;tt class="docutils literal"&gt;mount: /mnt/vdi: unknown filesystem type 'LVM2_member'.&lt;/tt&gt; error. You need to do before instead of the mount step:&lt;/p&gt;
&lt;ol class="arabic"&gt;
&lt;li&gt;&lt;p class="first"&gt;Identify the LVM volume with &lt;tt class="docutils literal"&gt;lvscan&lt;/tt&gt;. You should see a path to the LVM volume to mount. &lt;tt class="docutils literal"&gt;/dev/fedora/root&lt;/tt&gt; in may case with this output:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
ACTIVE            '/dev/fedora/swap' [3.00 GiB] inherit
ACTIVE            '/dev/fedora/root' [&amp;lt;26.00 GiB] inherit
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;You can then mount it with &lt;tt class="docutils literal"&gt;mount /dev/fedora/root /mnt/vdi/&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;To unmount, use &lt;tt class="docutils literal"&gt;umount /dev/fedora/root&lt;/tt&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Disable the virtual drive normally.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sources:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://stackoverflow.com/questions/16893306/how-can-i-extract-files-from-vdi"&gt;https://stackoverflow.com/questions/16893306/how-can-i-extract-files-from-vdi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://ask.xmodulo.com/mount-lvm-partition-linux.html"&gt;http://ask.xmodulo.com/mount-lvm-partition-linux.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="VirtualBox"></category><category term="Virtualisation"></category></entry><entry><title>Fusionner deux dépôts git</title><link href="//www.jujens.eu/posts/2015/Jan/17/fusionner-deux-depots-git/" rel="alternate"></link><published>2015-01-17T00:00:00+01:00</published><updated>2015-01-17T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-17:/posts/2015/Jan/17/fusionner-deux-depots-git/</id><summary type="html">&lt;p&gt;Récemment, j'ai eu besoin de fusionner deux dépôts en un seul. Ça se fait plutôt
bien. Voilà la procédure :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# On clone les dépots
&lt;/span&gt;git clone projet1
git clone projet2
&lt;span class="nb"&gt;cd&lt;/span&gt; projet1

&lt;span class="c1"&gt;# On ajoute le projet2 comme source dans le projet1
&lt;/span&gt;git remote add projet2 ../projet2
git fetch projet2

&lt;span class="c1"&gt;# On liste …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;Récemment, j'ai eu besoin de fusionner deux dépôts en un seul. Ça se fait plutôt
bien. Voilà la procédure :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# On clone les dépots
&lt;/span&gt;git clone projet1
git clone projet2
&lt;span class="nb"&gt;cd&lt;/span&gt; projet1

&lt;span class="c1"&gt;# On ajoute le projet2 comme source dans le projet1
&lt;/span&gt;git remote add projet2 ../projet2
git fetch projet2

&lt;span class="c1"&gt;# On liste les branches du dépôt 2
&lt;/span&gt;git branch -a

&lt;span class="c1"&gt;# On crée dans le dépôt 1 la branche à fusionner (par exemple master)
&lt;/span&gt;git branch projet2-master projet2/master

&lt;span class="c1"&gt;# On fusionne
&lt;/span&gt;git merge projet2-master
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Surtout ne pas tentez de faire directement un git pull projet2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Si vous avez des sous-modules, réinitialisez les avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git submodule update --init
&lt;/pre&gt;
&lt;p&gt;L'article (en anglais) qui m'a bien aidé :
&lt;a class="reference external" href="http://blog.caplin.com/2013/09/18/merging-two-git-repositories/"&gt;http://blog.caplin.com/2013/09/18/merging-two-git-repositories/&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="git"></category><category term="Linux"></category></entry><entry><title>Importer périodiquement un flux ical dans owncloud</title><link href="//www.jujens.eu/posts/2015/Jan/09/periodic-import-ical-owncloud/" rel="alternate"></link><published>2015-01-09T00:00:00+01:00</published><updated>2015-01-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-09:/posts/2015/Jan/09/periodic-import-ical-owncloud/</id><summary type="html">&lt;p&gt;J'ai toujours trouvé dommage que owncloud ne soit pas capable d'importer
périodiquement des calendriers que l'on trouve sur le web. Dans mon cas, mon
emploi du temps est un flux ical régulièrement mis à jour et j'aimerais bien que
owncloud soit capable de l'importer. Je me suis finalement résigné à …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai toujours trouvé dommage que owncloud ne soit pas capable d'importer
périodiquement des calendriers que l'on trouve sur le web. Dans mon cas, mon
emploi du temps est un flux ical régulièrement mis à jour et j'aimerais bien que
owncloud soit capable de l'importer. Je me suis finalement résigné à faire mon
propre script pour régler ce problème.&lt;/p&gt;
&lt;p&gt;Je pensais initialement le faire en Bash et utiliser &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt; pour faire les
requêtes vers owncloud. Cependant, un flux ical peut contenir des sauts de
lignes et les tenter de gérer correctement m'a fait souffrir. Du coup, je me
suis rabattu sur python et son excellente bibliothèque &lt;a class="reference external" href="http://docs.python-requests.org/en/latest/"&gt;requests&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Concrètement, ce script :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;lit dans &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.owncloud&lt;/span&gt;&lt;/tt&gt; l'adresse et les identifiants du serveur owncloud,&lt;/li&gt;
&lt;li&gt;récupère les événements définis dans les flux icals que je lui demande de
synchroniser. Ces événements sont stockés dans une instance de la classe
&lt;tt class="docutils literal"&gt;Vevent&lt;/tt&gt; crée à cet effet. J'ai ajouté la possibilité de filtrer certains
événements (pour exclure des cours que je n'ai pas),&lt;/li&gt;
&lt;li&gt;supprime les événements présents dans owncloud mais absent des flux icals,&lt;/li&gt;
&lt;li&gt;poste (crée ou met à jour) les événements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il ne reste plus qu'à mettre le script dans un cron pour faire l'import
périodiquement.&lt;/p&gt;
&lt;p&gt;Normalement le script est assez simple et clair pour être facilement
compréhensible. En cas de problème, postez un commentaire.&lt;/p&gt;
&lt;p&gt;Vous pouvez aussi &lt;a class="reference external" href="//www.jujens.eu/static/periodic-import-ical-owncloud/edt.py"&gt;télécharger ce script&lt;/a&gt; et le voir sur &lt;a class="reference external" href="https://bitbucket.org/Jenselme/server-bin/src/469c28a3ae87228f1ac3f3d0ad57349dda77e5b8/edt.py?at=default"&gt;le
dépôt mercurial&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ln"&gt;  1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/python3&lt;/span&gt;
&lt;span class="ln"&gt;  2 &lt;/span&gt;
&lt;span class="ln"&gt;  3 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="ln"&gt;  4 &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;requests.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTTPBasicAuth&lt;/span&gt;
&lt;span class="ln"&gt;  5 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="ln"&gt;  6 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;ET&lt;/span&gt;
&lt;span class="ln"&gt;  7 &lt;/span&gt;
&lt;span class="ln"&gt;  8 &lt;/span&gt;
&lt;span class="ln"&gt;  9 &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vevent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 10 &lt;/span&gt;    &lt;span class="n"&gt;UID_REGEXP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'^UID:.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 11 &lt;/span&gt;    &lt;span class="n"&gt;SUMMARY_REGEXP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'^SUMMARY:.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 12 &lt;/span&gt;
&lt;span class="ln"&gt; 13 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 14 &lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;
&lt;span class="ln"&gt; 15 &lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_line_from_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UID_REGEXP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 16 &lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_line_from_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SUMMARY_REGEXP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 17 &lt;/span&gt;
&lt;span class="ln"&gt; 18 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_line_from_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 19 &lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 20 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 21 &lt;/span&gt;                &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 22 &lt;/span&gt;                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 23 &lt;/span&gt;
&lt;span class="ln"&gt; 24 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_vevent_for_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 25 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 26 &lt;/span&gt;
&lt;span class="ln"&gt; 27 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_as_vcal_for_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 28 &lt;/span&gt;        &lt;span class="n"&gt;str_vevent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'BEGIN:VCALENDAR&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_vevent_for_put&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; \
&lt;span class="ln"&gt; 29 &lt;/span&gt;                     &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;END:VCALENDAR'&lt;/span&gt;
&lt;span class="ln"&gt; 30 &lt;/span&gt;        &lt;span class="c1"&gt;# If you experience problem with the line below, try&lt;/span&gt;
&lt;span class="ln"&gt; 31 &lt;/span&gt;        &lt;span class="c1"&gt;# return strvevent&lt;/span&gt;
&lt;span class="ln"&gt; 32 &lt;/span&gt;        &lt;span class="c1"&gt;# instead&lt;/span&gt;
&lt;span class="ln"&gt; 33 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str_vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 34 &lt;/span&gt;
&lt;span class="ln"&gt; 35 &lt;/span&gt;    &lt;span class="nd"&gt;&amp;#64;property&lt;/span&gt;
&lt;span class="ln"&gt; 36 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 37 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_uid&lt;/span&gt;
&lt;span class="ln"&gt; 38 &lt;/span&gt;
&lt;span class="ln"&gt; 39 &lt;/span&gt;    &lt;span class="nd"&gt;&amp;#64;property&lt;/span&gt;
&lt;span class="ln"&gt; 40 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 41 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_summary&lt;/span&gt;
&lt;span class="ln"&gt; 42 &lt;/span&gt;
&lt;span class="ln"&gt; 43 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 44 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 45 &lt;/span&gt;
&lt;span class="ln"&gt; 46 &lt;/span&gt;
&lt;span class="ln"&gt; 47 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_login&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="ln"&gt; 48 &lt;/span&gt;    &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 49 &lt;/span&gt;    &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 50 &lt;/span&gt;    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 51 &lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/home/jenselme/.owncloud'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;owncloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 52 &lt;/span&gt;        &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;
&lt;span class="ln"&gt; 53 &lt;/span&gt;                                              &lt;span class="n"&gt;owncloud&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 54 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
&lt;span class="ln"&gt; 55 &lt;/span&gt;
&lt;span class="ln"&gt; 56 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_all_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filter_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 57 &lt;/span&gt;    &lt;span class="n"&gt;vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 58 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="ln"&gt; 59 &lt;/span&gt;        &lt;span class="n"&gt;current_vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 60 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filter_dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 61 &lt;/span&gt;            &lt;span class="n"&gt;current_vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;current_vevents&lt;/span&gt;
&lt;span class="ln"&gt; 62 &lt;/span&gt;                               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filter_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="ln"&gt; 63 &lt;/span&gt;        &lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_vevents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 64 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vevents&lt;/span&gt;
&lt;span class="ln"&gt; 65 &lt;/span&gt;
&lt;span class="ln"&gt; 66 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 67 &lt;/span&gt;    &lt;span class="n"&gt;calendar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 68 &lt;/span&gt;    &lt;span class="n"&gt;calendar_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 69 &lt;/span&gt;    &lt;span class="c1"&gt;# Remove VCALENDAR lines&lt;/span&gt;
&lt;span class="ln"&gt; 70 &lt;/span&gt;    &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;calendar_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 71 &lt;/span&gt;    &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;calendar_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 72 &lt;/span&gt;
&lt;span class="ln"&gt; 73 &lt;/span&gt;    &lt;span class="n"&gt;vevent_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 74 &lt;/span&gt;    &lt;span class="n"&gt;vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 75 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calendar_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 76 &lt;/span&gt;        &lt;span class="n"&gt;vevent_lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 77 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;VEVENT_END&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;vevent_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 78 &lt;/span&gt;            &lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vevent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vevent_lines&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="ln"&gt; 79 &lt;/span&gt;            &lt;span class="n"&gt;vevent_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 80 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vevents&lt;/span&gt;
&lt;span class="ln"&gt; 81 &lt;/span&gt;
&lt;span class="ln"&gt; 82 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_all_removed_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetch_vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 83 &lt;/span&gt;    &lt;span class="n"&gt;destination_uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_destination_calendar_uids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 84 &lt;/span&gt;    &lt;span class="n"&gt;source_uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fetch_vevents&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 85 &lt;/span&gt;    &lt;span class="n"&gt;removed_from_source_uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;destination_uids&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;source_uids&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 86 &lt;/span&gt;    &lt;span class="n"&gt;delete_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;removed_from_source_uids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 87 &lt;/span&gt;
&lt;span class="ln"&gt; 88 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_destination_calendar_uids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 89 &lt;/span&gt;    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PROPFIND'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 90 &lt;/span&gt;    &lt;span class="n"&gt;xml_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 91 &lt;/span&gt;    &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 92 &lt;/span&gt;    &lt;span class="n"&gt;hrefs_uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 93 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 94 &lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 95 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{DAV:}&lt;/span&gt;&lt;span class="s1"&gt;href'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 96 &lt;/span&gt;                &lt;span class="n"&gt;hrefs_uid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 97 &lt;/span&gt;    &lt;span class="n"&gt;uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 98 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hrefs_uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 99 &lt;/span&gt;        &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt;100 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;101 &lt;/span&gt;            &lt;span class="n"&gt;uids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;102 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;uids&lt;/span&gt;
&lt;span class="ln"&gt;103 &lt;/span&gt;
&lt;span class="ln"&gt;104 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;105 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;uids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;106 &lt;/span&gt;        &lt;span class="n"&gt;delete_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;107 &lt;/span&gt;        &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delete_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;108 &lt;/span&gt;
&lt;span class="ln"&gt;109 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;put_all_vevents_as_vcalendars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calendar_put_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;110 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;111 &lt;/span&gt;        &lt;span class="n"&gt;put_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;.ics'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calendar_put_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;112 &lt;/span&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_as_vcal_for_put&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt;113 &lt;/span&gt;        &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;put_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;114 &lt;/span&gt;
&lt;span class="ln"&gt;115 &lt;/span&gt;
&lt;span class="ln"&gt;116 &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;117 &lt;/span&gt;    &lt;span class="c1"&gt;# Global variables&lt;/span&gt;
&lt;span class="ln"&gt;118 &lt;/span&gt;    &lt;span class="n"&gt;VEVENT_END&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'^END:VEVENT$'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;119 &lt;/span&gt;    &lt;span class="n"&gt;SOCIOLOGIE_ORGANISATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.*Sociologie des Organisations.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;120 &lt;/span&gt;    &lt;span class="n"&gt;EDT_FETCH_URLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'omis-org'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=804&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2015-01-06&amp;amp;lastDate=2015-06-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;121 &lt;/span&gt;    &lt;span class="s1"&gt;'tc-electif'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=1043&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-11-24&amp;amp;lastDate=2015-04-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;122 &lt;/span&gt;    &lt;span class="s1"&gt;'ENT'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=208&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-10-20&amp;amp;lastDate=2015-05-31'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;123 &lt;/span&gt;    &lt;span class="s1"&gt;'omis-gB'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=507&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-09-15&amp;amp;lastDate=2015-05-31'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;124 &lt;/span&gt;    &lt;span class="s1"&gt;'tc2-td3'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=194&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-09-01&amp;amp;lastDate=2015-06-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;125 &lt;/span&gt;    &lt;span class="s1"&gt;'omis-i'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=814&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-09-01&amp;amp;lastDate=2015-05-31'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;126 &lt;/span&gt;
&lt;span class="ln"&gt;127 &lt;/span&gt;    &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt;128 &lt;/span&gt;
&lt;span class="ln"&gt;129 &lt;/span&gt;    &lt;span class="n"&gt;request_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'verify'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HTTPBasicAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="ln"&gt;130 &lt;/span&gt;    &lt;span class="n"&gt;fetched_vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fetch_all_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EDT_FETCH_URLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'omis-org'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SOCIOLOGIE_ORGANISATION&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="ln"&gt;131 &lt;/span&gt;    &lt;span class="n"&gt;delete_all_removed_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetched_vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;132 &lt;/span&gt;    &lt;span class="n"&gt;put_all_vevents_as_vcalendars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetched_vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="Python"></category><category term="Calbdav"></category><category term="Owncloud"></category></entry><entry><title>Un shell pour pelican</title><link href="//www.jujens.eu/posts/2015/Jan/09/shell-pelican/" rel="alternate"></link><published>2015-01-09T00:00:00+01:00</published><updated>2015-01-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-09:/posts/2015/Jan/09/shell-pelican/</id><summary type="html">&lt;p&gt;Comme je l'ai déjà dit &lt;a class="reference external" href="//www.jujens.eu/posts/2014/Apr/22/passage-pelican/"&gt;ici&lt;/a&gt;, mon blog est géré par
&lt;a class="reference external" href="http://docs.getpelican.com"&gt;Pelican&lt;/a&gt;. Il est également placé sous gestion de
version. Pour régénérer automatiquement après chaque modification la version
html des pages, il faut utiliser la commande &lt;tt class="docutils literal"&gt;make regenerate&lt;/tt&gt;. Pour lancer le
serveur de test pour voir les pages, on utilise …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Comme je l'ai déjà dit &lt;a class="reference external" href="//www.jujens.eu/posts/2014/Apr/22/passage-pelican/"&gt;ici&lt;/a&gt;, mon blog est géré par
&lt;a class="reference external" href="http://docs.getpelican.com"&gt;Pelican&lt;/a&gt;. Il est également placé sous gestion de
version. Pour régénérer automatiquement après chaque modification la version
html des pages, il faut utiliser la commande &lt;tt class="docutils literal"&gt;make regenerate&lt;/tt&gt;. Pour lancer le
serveur de test pour voir les pages, on utilise &lt;tt class="docutils literal"&gt;make serve&lt;/tt&gt;. Enfin, pour
synchroniser le contenu sur le serveur, j'utilise &lt;tt class="docutils literal"&gt;make rsync_upload&lt;/tt&gt;. J'en
profite pour pousser les modifications de mon dépôt local vers mon serveur et
vers &lt;a class="reference external" href="https://bitbucket.org/Jenselme/www.jujens.eu/overview"&gt;Bitbucket&lt;/a&gt; pour
en avoir une copie de sauvegarde.&lt;/p&gt;
&lt;p&gt;Jusqu'à présent, je gérais tout ça à la main, dans un terminal. J'avais déjà
écrit une petite fonction bash pour me déplacer dans le bon dossier et activer
le venv python. Mais ce n'était pas très pratique : les commandes &lt;tt class="docutils literal"&gt;make serve&lt;/tt&gt;
et &lt;tt class="docutils literal"&gt;make regenerate&lt;/tt&gt; doivent tourner en permanence en tâche de fond, il faut
pusher sur deux dépôts différents et synchroniser les pages sur le serveur. J'ai
donc décider de me créer un script pour améliorer tout ça.&lt;/p&gt;
&lt;p&gt;Comme j'ai besoin de lancer plusieurs commandes bien définies dans un même
dossier, sans sortir de l'environnement virtuel et que je veux pouvoir
interagir facilement avec les processus en tâche de fond, j'ai décidé de créer
un mini-shell. Je dois admettre que j'en suis très satisfait.&lt;/p&gt;
&lt;p&gt;Quelques explications sur le script :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Tout est dans une boucle infinie pour imiter un vrai shell. &lt;tt class="docutils literal"&gt;echo &lt;span class="pre"&gt;-ne&lt;/span&gt; &amp;quot;&amp;gt; &amp;quot;&lt;/tt&gt;
permet d'afficher un prompt et de laisser le curseur sur cette ligne.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;exec 3&amp;lt; &amp;lt;(make serve)&lt;/tt&gt;&lt;ul&gt;
&lt;li&gt;La syntaxe &lt;tt class="docutils literal"&gt;&amp;lt;(make serve)&lt;/tt&gt; est remplacée par chemin vers un fichier
virtuel qui est connecté à la sortie standard de la commande située entre
les parenthèses. Ici &lt;tt class="docutils literal"&gt;make serve&lt;/tt&gt; qui démarre le serveur.&lt;/li&gt;
&lt;li&gt;Comme on veut que le processus soit en background, on lance la commande avec
&lt;tt class="docutils literal"&gt;exec&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Enfin, comme on veut pouvoir récupérer facilement la sortie de la commande,
on envoie le contenu du fichier vers une nouvelle sortie 3. On lit son
contenu avec &lt;tt class="docutils literal"&gt;cat &amp;lt;&amp;amp;3&lt;/tt&gt;. &lt;strong&gt;Tant que le fichier n'est pas fermé, cette
commande ne se retourne pas.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Voir &lt;a class="reference external" href="http://stackoverflow.com/questions/20017805/bash-capture-output-of-command-run-in-background?answertab=active#tab-top"&gt;cette réponse sur stackoverflow&lt;/a&gt;
pour plus de détails.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sorties additionnelles : j'ai tenté de stocker le numéro des sorties dans des
variables. Le code est plus clair et cela permet de le
factoriser. Malheureusement, &lt;tt class="docutils literal"&gt;exec &lt;span class="pre"&gt;&amp;quot;${var}&amp;quot;&amp;lt;&lt;/span&gt; &amp;lt;(make serve)&lt;/tt&gt; provoque une
erreur. Idem pour &lt;tt class="docutils literal"&gt;cat &lt;span class="pre"&gt;&amp;lt;&amp;amp;&amp;quot;${var}&amp;quot;&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;[ &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;&amp;quot;${serve_pid}&amp;quot;&lt;/span&gt; ] &amp;amp;&amp;amp; has_died &lt;span class="pre"&gt;&amp;quot;${serve_pid}&amp;quot;&lt;/span&gt;&lt;/tt&gt; : la fonction
&lt;tt class="docutils literal"&gt;has_died&lt;/tt&gt; ne doit pas être entre crochets (donc passée en argument à la
fonction &lt;tt class="docutils literal"&gt;test&lt;/tt&gt;) pour que le script fonctionne correctement.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;echo ${pid}&lt;/tt&gt; : on ne peut pas renvoyer autre chose que des codes d'erreur avec
&lt;tt class="docutils literal"&gt;return&lt;/tt&gt;. Pour tout le reste, il faut utiliser &lt;tt class="docutils literal"&gt;echo&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ci-dessous le script complet. Vous pouvez aussi le &lt;a class="reference external" href="//www.jujens.eu/static/shell-pelican/blog.sh"&gt;télécharger&lt;/a&gt; ou le &lt;a class="reference external" href="https://github.com/Jenselme/dot-files-shell/blob/master/bin/blog.sh"&gt;voir sur github&lt;/a&gt; pour
avoir la version la plus à jour.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ln"&gt;  1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/bash
&lt;/span&gt;&lt;span class="ln"&gt;  2 &lt;/span&gt;&lt;span class="ch"&gt;&lt;/span&gt;
&lt;span class="ln"&gt;  3 &lt;/span&gt;stop_command&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;  4 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt;  5 &lt;/span&gt;        &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;  6 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt;  7 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;  8 &lt;/span&gt;
&lt;span class="ln"&gt;  9 &lt;/span&gt;has_died&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 10 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;kill&lt;/span&gt; -0 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; /dev/null &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 11 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="ln"&gt; 12 &lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="ln"&gt; 13 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="ln"&gt; 14 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 15 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 16 &lt;/span&gt;
&lt;span class="ln"&gt; 17 &lt;/span&gt;find_pid&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 18 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;ps -elf &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -v &lt;span class="s1"&gt;'&amp;amp;&amp;amp;'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -v &lt;span class="s1"&gt;'grep'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;'{print $4}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 19 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 20 &lt;/span&gt;
&lt;span class="ln"&gt; 21 &lt;/span&gt;get_pid&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 22 &lt;/span&gt;    &lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find_pid &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 23 &lt;/span&gt;    &lt;span class="k"&gt;until&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="ln"&gt; 24 &lt;/span&gt;        &lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find_pid &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 25 &lt;/span&gt;    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="ln"&gt; 26 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 27 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 28 &lt;/span&gt;
&lt;span class="ln"&gt; 29 &lt;/span&gt;&lt;span class="c1"&gt;# Activate venv
&lt;/span&gt;&lt;span class="ln"&gt; 30 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/server/blog/
&lt;span class="ln"&gt; 31 &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; bin/activate
&lt;span class="ln"&gt; 32 &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; pelican/jujens.eu
&lt;span class="ln"&gt; 33 &lt;/span&gt;
&lt;span class="ln"&gt; 34 &lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 35 &lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 36 &lt;/span&gt;&lt;span class="c1"&gt;# These variables cannot be used. If you try to use them, you will get an error like 3&amp;lt; not found.
&lt;/span&gt;&lt;span class="ln"&gt; 37 &lt;/span&gt;&lt;span class="c1"&gt;#regenerate_output=3
&lt;/span&gt;&lt;span class="ln"&gt; 38 &lt;/span&gt;&lt;span class="c1"&gt;#serve_output=4
&lt;/span&gt;&lt;span class="ln"&gt; 39 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;
&lt;span class="ln"&gt; 40 &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="ln"&gt; 41 &lt;/span&gt;    &lt;span class="c1"&gt;# Print errors for regenerate
&lt;/span&gt;&lt;span class="ln"&gt; 42 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 43 &lt;/span&gt;        &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;Regenerate has died with ouput:\n&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 44 &lt;/span&gt;        cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="ln"&gt; 45 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 46 &lt;/span&gt;    &lt;span class="c1"&gt;# Print errors for serve
&lt;/span&gt;&lt;span class="ln"&gt; 47 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 48 &lt;/span&gt;        &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;Serve has died with ouput:\n&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 49 &lt;/span&gt;        cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="ln"&gt; 50 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 51 &lt;/span&gt;
&lt;span class="ln"&gt; 52 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; -en &lt;span class="s2"&gt;&amp;quot;(blog) &amp;gt; &amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 53 &lt;/span&gt;    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;span class="ln"&gt; 54 &lt;/span&gt;
&lt;span class="ln"&gt; 55 &lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
&lt;span class="ln"&gt; 56 &lt;/span&gt;        deploy&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 57 &lt;/span&gt;            hg push &amp;gt; /dev/null
&lt;span class="ln"&gt; 58 &lt;/span&gt;            hg push bitbucket &amp;gt;/dev/null
&lt;span class="ln"&gt; 59 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 60 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 61 &lt;/span&gt;            &lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 62 &lt;/span&gt;            &lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 63 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &amp;gt; /dev/null &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="ln"&gt; 64 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &amp;gt; /dev/null &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="ln"&gt; 65 &lt;/span&gt;            make rsync_upload &amp;gt; /dev/null
&lt;span class="ln"&gt; 66 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 67 &lt;/span&gt;        push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 68 &lt;/span&gt;            hg push &amp;gt; /dev/null
&lt;span class="ln"&gt; 69 &lt;/span&gt;            hg push bitbucket &amp;gt; /dev/null
&lt;span class="ln"&gt; 70 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 71 &lt;/span&gt;        st&lt;span class="p"&gt;|&lt;/span&gt;status&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 72 &lt;/span&gt;            hg st
&lt;span class="ln"&gt; 73 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 74 &lt;/span&gt;        add&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 75 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Enter the filename to add (. for all files)&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 76 &lt;/span&gt;            &lt;span class="nb"&gt;read&lt;/span&gt; file_name
&lt;span class="ln"&gt; 77 &lt;/span&gt;            hg add &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 78 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 79 &lt;/span&gt;        ci&lt;span class="p"&gt;|&lt;/span&gt;commit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 80 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Please enter the commit message:&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 81 &lt;/span&gt;            &lt;span class="nb"&gt;read&lt;/span&gt; commit_msg
&lt;span class="ln"&gt; 82 &lt;/span&gt;            hg ci -m &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;commit_msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 83 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 84 &lt;/span&gt;        serve&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 85 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ! has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 86 &lt;/span&gt;                &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Serve is already running.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 87 &lt;/span&gt;            &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="ln"&gt; 88 &lt;/span&gt;                &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;make serve &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 89 &lt;/span&gt;                &lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_pid &lt;span class="s1"&gt;'python3 -m pelican.server'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 90 &lt;/span&gt;            &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 91 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 92 &lt;/span&gt;        regenerate&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 93 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ! has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 94 &lt;/span&gt;                &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Regenerate is already running.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 95 &lt;/span&gt;            &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="ln"&gt; 96 &lt;/span&gt;                &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;make regenerate &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 97 &lt;/span&gt;                &lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_pid &lt;span class="s1"&gt;'make regenerate'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 98 &lt;/span&gt;            &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 99 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;100 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;stop serve&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;101 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;102 &lt;/span&gt;            &lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt;103 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;104 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;105 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;stop regenerate&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;106 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;107 &lt;/span&gt;            &lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt;108 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;109 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;110 &lt;/span&gt;        stop&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;111 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Stop requires an argument: serve or regenerate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;112 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;113 &lt;/span&gt;        quit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;114 &lt;/span&gt;            &lt;span class="nb"&gt;break&lt;/span&gt;
&lt;span class="ln"&gt;115 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;116 &lt;/span&gt;        &lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;117 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Available commands:&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;118 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tdeploy&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;119 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tpush&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;120 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tserve&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;121 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tregenerate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;122 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tstop serve&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;123 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tstop regenerate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;124 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\thelp&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;125 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;126 &lt;/span&gt;        *&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;127 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt;128 &lt;/span&gt;                &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is invalid.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;129 &lt;/span&gt;            &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt;130 &lt;/span&gt;    &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="ln"&gt;131 &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="ln"&gt;132 &lt;/span&gt;
&lt;span class="ln"&gt;133 &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Done&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="Bash/Shell"></category><category term="Linux"></category><category term="Pelican"></category></entry><entry><title>Utiliser trap en bash pour pièger des signaux</title><link href="//www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/" rel="alternate"></link><published>2015-01-09T00:00:00+01:00</published><updated>2015-01-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-09:/posts/2015/Jan/09/utiliser-trap-bash/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Mise à jour 2017-09-96:&lt;/strong&gt; ajout d'un exemple d'utilisation des noms des signaux. Merci à &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-18"&gt;Thomas&lt;/a&gt; et &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-127"&gt;Lokta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bash est capable d'intercepter les signaux envoyés par certains raccourcis
claviers (comme Ctrl-C) et de changer le comportement par défaut de ces
raccourcis. Il suffit pour cela d'utiliser la commande &lt;tt class="docutils literal"&gt;trap&lt;/tt&gt;. Elle prend …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Mise à jour 2017-09-96:&lt;/strong&gt; ajout d'un exemple d'utilisation des noms des signaux. Merci à &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-18"&gt;Thomas&lt;/a&gt; et &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-127"&gt;Lokta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bash est capable d'intercepter les signaux envoyés par certains raccourcis
claviers (comme Ctrl-C) et de changer le comportement par défaut de ces
raccourcis. Il suffit pour cela d'utiliser la commande &lt;tt class="docutils literal"&gt;trap&lt;/tt&gt;. Elle prend en
premier argument la commande à exécuter puis les signaux sur lesquels elle doit
réagir.&lt;/p&gt;
&lt;p&gt;Par exemple :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;echo yollo&amp;quot;&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;affichera &lt;tt class="docutils literal"&gt;yollo&lt;/tt&gt; quand on fait &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Ctrl-C&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;On obtient la liste des signaux avec leurs numéros et leurs noms avec la commande
&lt;tt class="docutils literal"&gt;kill&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;kill&lt;/span&gt; -l
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGHUP       &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGINT       &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGQUIT      &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGILL
&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGTRAP      &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGABRT      &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGEMT       &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGFPE
&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;SIGKILL     &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGBUS      &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGSEGV     &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGSYS
&lt;/pre&gt;
&lt;p&gt;Pour utiliser les noms des signaux, utiliser:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;echo 'sig INT caught' &amp;quot;&lt;/span&gt; INT
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Linux"></category><category term="Bash/Shell"></category></entry><entry><title>Periodically import an ical calendar into owncloud</title><link href="//www.jujens.eu/posts/en/2015/Jan/09/periodic-import-ical-owncloud/" rel="alternate"></link><published>2015-01-09T00:00:00+01:00</published><updated>2015-01-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-09:/posts/en/2015/Jan/09/periodic-import-ical-owncloud/</id><summary type="html">&lt;p&gt;I always thought that owncloud should be able to periodically import calendars
found on the web. In my case, I have a schedule as an ical feed I would like
synchronize with my owncloud. I finally wrote a script to do that.&lt;/p&gt;
&lt;p&gt;Initially, I intended to do it in Bash …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I always thought that owncloud should be able to periodically import calendars
found on the web. In my case, I have a schedule as an ical feed I would like
synchronize with my owncloud. I finally wrote a script to do that.&lt;/p&gt;
&lt;p&gt;Initially, I intended to do it in Bash and to use &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt; to do requests to
owncloud. However, an ical feed contains line breaks. I had a lot of problems to
manage them correctly. So I wrote my script in python the &lt;a class="reference external" href="http://docs.python-requests.org/en/latest/"&gt;excellent requests
library&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This script :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;reads in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.owncloud&lt;/span&gt;&lt;/tt&gt; the address and the ids of the owncloud server,&lt;/li&gt;
&lt;li&gt;fetches the events described in the ical feed I ask it to synchronize. Theses
events are stored in an instance of &lt;tt class="docutils literal"&gt;Vevent&lt;/tt&gt;. I had the possibility to
filter out some events,&lt;/li&gt;
&lt;li&gt;deletes the events present in my owncloud but not in the ical feeds,&lt;/li&gt;
&lt;li&gt;put (create or update) the events in owncloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think this script is simple and clear enough to be easily read. In case of
troubles, you can post a comment.&lt;/p&gt;
&lt;p&gt;You can also &lt;a class="reference external" href="//www.jujens.eu/static/periodic-import-ical-owncloud/edt.py"&gt;download this script&lt;/a&gt; and see it &lt;a class="reference external" href="https://bitbucket.org/Jenselme/server-bin/src/469c28a3ae87228f1ac3f3d0ad57349dda77e5b8/edt.py?at=default"&gt;on my
mercurial on bitbucket&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="ln"&gt;  1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/python3&lt;/span&gt;
&lt;span class="ln"&gt;  2 &lt;/span&gt;
&lt;span class="ln"&gt;  3 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="ln"&gt;  4 &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;requests.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTTPBasicAuth&lt;/span&gt;
&lt;span class="ln"&gt;  5 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="ln"&gt;  6 &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;ET&lt;/span&gt;
&lt;span class="ln"&gt;  7 &lt;/span&gt;
&lt;span class="ln"&gt;  8 &lt;/span&gt;
&lt;span class="ln"&gt;  9 &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vevent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 10 &lt;/span&gt;    &lt;span class="n"&gt;UID_REGEXP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'^UID:.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 11 &lt;/span&gt;    &lt;span class="n"&gt;SUMMARY_REGEXP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'^SUMMARY:.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 12 &lt;/span&gt;
&lt;span class="ln"&gt; 13 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 14 &lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;
&lt;span class="ln"&gt; 15 &lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_line_from_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UID_REGEXP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 16 &lt;/span&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_line_from_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SUMMARY_REGEXP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 17 &lt;/span&gt;
&lt;span class="ln"&gt; 18 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_line_from_regexp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 19 &lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 20 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 21 &lt;/span&gt;                &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 22 &lt;/span&gt;                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 23 &lt;/span&gt;
&lt;span class="ln"&gt; 24 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_vevent_for_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 25 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 26 &lt;/span&gt;
&lt;span class="ln"&gt; 27 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_as_vcal_for_put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 28 &lt;/span&gt;        &lt;span class="n"&gt;str_vevent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'BEGIN:VCALENDAR&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_vevent_for_put&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; \
&lt;span class="ln"&gt; 29 &lt;/span&gt;                     &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;END:VCALENDAR'&lt;/span&gt;
&lt;span class="ln"&gt; 30 &lt;/span&gt;        &lt;span class="c1"&gt;# If you experience problem with the line below, try&lt;/span&gt;
&lt;span class="ln"&gt; 31 &lt;/span&gt;        &lt;span class="c1"&gt;# return strvevent&lt;/span&gt;
&lt;span class="ln"&gt; 32 &lt;/span&gt;        &lt;span class="c1"&gt;# instead&lt;/span&gt;
&lt;span class="ln"&gt; 33 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;str_vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 34 &lt;/span&gt;
&lt;span class="ln"&gt; 35 &lt;/span&gt;    &lt;span class="nd"&gt;&amp;#64;property&lt;/span&gt;
&lt;span class="ln"&gt; 36 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 37 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_uid&lt;/span&gt;
&lt;span class="ln"&gt; 38 &lt;/span&gt;
&lt;span class="ln"&gt; 39 &lt;/span&gt;    &lt;span class="nd"&gt;&amp;#64;property&lt;/span&gt;
&lt;span class="ln"&gt; 40 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 41 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_summary&lt;/span&gt;
&lt;span class="ln"&gt; 42 &lt;/span&gt;
&lt;span class="ln"&gt; 43 &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 44 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_uid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 45 &lt;/span&gt;
&lt;span class="ln"&gt; 46 &lt;/span&gt;
&lt;span class="ln"&gt; 47 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_login&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="ln"&gt; 48 &lt;/span&gt;    &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 49 &lt;/span&gt;    &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 50 &lt;/span&gt;    &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 51 &lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/home/jenselme/.owncloud'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;owncloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 52 &lt;/span&gt;        &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;
&lt;span class="ln"&gt; 53 &lt;/span&gt;                                              &lt;span class="n"&gt;owncloud&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 54 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;
&lt;span class="ln"&gt; 55 &lt;/span&gt;
&lt;span class="ln"&gt; 56 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_all_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filter_dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 57 &lt;/span&gt;    &lt;span class="n"&gt;vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 58 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="ln"&gt; 59 &lt;/span&gt;        &lt;span class="n"&gt;current_vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 60 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filter_dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 61 &lt;/span&gt;            &lt;span class="n"&gt;current_vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;current_vevents&lt;/span&gt;
&lt;span class="ln"&gt; 62 &lt;/span&gt;                               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filter_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="ln"&gt; 63 &lt;/span&gt;        &lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_vevents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 64 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vevents&lt;/span&gt;
&lt;span class="ln"&gt; 65 &lt;/span&gt;
&lt;span class="ln"&gt; 66 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 67 &lt;/span&gt;    &lt;span class="n"&gt;calendar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 68 &lt;/span&gt;    &lt;span class="n"&gt;calendar_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 69 &lt;/span&gt;    &lt;span class="c1"&gt;# Remove VCALENDAR lines&lt;/span&gt;
&lt;span class="ln"&gt; 70 &lt;/span&gt;    &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;calendar_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 71 &lt;/span&gt;    &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;calendar_lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 72 &lt;/span&gt;
&lt;span class="ln"&gt; 73 &lt;/span&gt;    &lt;span class="n"&gt;vevent_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 74 &lt;/span&gt;    &lt;span class="n"&gt;vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 75 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calendar_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 76 &lt;/span&gt;        &lt;span class="n"&gt;vevent_lines&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 77 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;VEVENT_END&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;vevent_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 78 &lt;/span&gt;            &lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Vevent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vevent_lines&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="ln"&gt; 79 &lt;/span&gt;            &lt;span class="n"&gt;vevent_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 80 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vevents&lt;/span&gt;
&lt;span class="ln"&gt; 81 &lt;/span&gt;
&lt;span class="ln"&gt; 82 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_all_removed_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetch_vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 83 &lt;/span&gt;    &lt;span class="n"&gt;destination_uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_destination_calendar_uids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 84 &lt;/span&gt;    &lt;span class="n"&gt;source_uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fetch_vevents&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 85 &lt;/span&gt;    &lt;span class="n"&gt;removed_from_source_uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;destination_uids&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;source_uids&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt; 86 &lt;/span&gt;    &lt;span class="n"&gt;delete_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;removed_from_source_uids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 87 &lt;/span&gt;
&lt;span class="ln"&gt; 88 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_destination_calendar_uids&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt; 89 &lt;/span&gt;    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'PROPFIND'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 90 &lt;/span&gt;    &lt;span class="n"&gt;xml_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'utf-8'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 91 &lt;/span&gt;    &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 92 &lt;/span&gt;    &lt;span class="n"&gt;hrefs_uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 93 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 94 &lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 95 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{DAV:}&lt;/span&gt;&lt;span class="s1"&gt;href'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 96 &lt;/span&gt;                &lt;span class="n"&gt;hrefs_uid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 97 &lt;/span&gt;    &lt;span class="n"&gt;uids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="ln"&gt; 98 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hrefs_uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt; 99 &lt;/span&gt;        &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;href&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="ln"&gt;100 &lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;101 &lt;/span&gt;            &lt;span class="n"&gt;uids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;102 &lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;uids&lt;/span&gt;
&lt;span class="ln"&gt;103 &lt;/span&gt;
&lt;span class="ln"&gt;104 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;105 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;uids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;106 &lt;/span&gt;        &lt;span class="n"&gt;delete_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;107 &lt;/span&gt;        &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delete_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;108 &lt;/span&gt;
&lt;span class="ln"&gt;109 &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;put_all_vevents_as_vcalendars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calendar_put_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="ln"&gt;110 &lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;vevents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;111 &lt;/span&gt;        &lt;span class="n"&gt;put_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;.ics'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calendar_put_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;112 &lt;/span&gt;        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vevent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_as_vcal_for_put&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt;113 &lt;/span&gt;        &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;put_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;114 &lt;/span&gt;
&lt;span class="ln"&gt;115 &lt;/span&gt;
&lt;span class="ln"&gt;116 &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="ln"&gt;117 &lt;/span&gt;    &lt;span class="c1"&gt;# Global variables&lt;/span&gt;
&lt;span class="ln"&gt;118 &lt;/span&gt;    &lt;span class="n"&gt;VEVENT_END&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'^END:VEVENT$'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;119 &lt;/span&gt;    &lt;span class="n"&gt;SOCIOLOGIE_ORGANISATION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.*Sociologie des Organisations.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;120 &lt;/span&gt;    &lt;span class="n"&gt;EDT_FETCH_URLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'omis-org'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=804&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2015-01-06&amp;amp;lastDate=2015-06-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;121 &lt;/span&gt;    &lt;span class="s1"&gt;'tc-electif'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=1043&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-11-24&amp;amp;lastDate=2015-04-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;122 &lt;/span&gt;    &lt;span class="s1"&gt;'ENT'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=208&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-10-20&amp;amp;lastDate=2015-05-31'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;123 &lt;/span&gt;    &lt;span class="s1"&gt;'omis-gB'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=507&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-09-15&amp;amp;lastDate=2015-05-31'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;124 &lt;/span&gt;    &lt;span class="s1"&gt;'tc2-td3'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=194&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-09-01&amp;amp;lastDate=2015-06-30'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="ln"&gt;125 &lt;/span&gt;    &lt;span class="s1"&gt;'omis-i'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=814&amp;amp;projectId=15&amp;amp;calType=ical&amp;amp;firstDate=2014-09-01&amp;amp;lastDate=2015-05-31'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;126 &lt;/span&gt;
&lt;span class="ln"&gt;127 &lt;/span&gt;    &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="ln"&gt;128 &lt;/span&gt;
&lt;span class="ln"&gt;129 &lt;/span&gt;    &lt;span class="n"&gt;request_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'verify'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;HTTPBasicAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="ln"&gt;130 &lt;/span&gt;    &lt;span class="n"&gt;fetched_vevents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fetch_all_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EDT_FETCH_URLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'omis-org'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SOCIOLOGIE_ORGANISATION&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="ln"&gt;131 &lt;/span&gt;    &lt;span class="n"&gt;delete_all_removed_vevents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetched_vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;132 &lt;/span&gt;    &lt;span class="n"&gt;put_all_vevents_as_vcalendars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetched_vevents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;owncloud_omis_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="Python"></category><category term="Calbdav"></category><category term="Owncloud"></category></entry><entry><title>A basic shell for pelican</title><link href="//www.jujens.eu/posts/en/2015/Jan/09/shell-pelican/" rel="alternate"></link><published>2015-01-09T00:00:00+01:00</published><updated>2015-01-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-09:/posts/en/2015/Jan/09/shell-pelican/</id><summary type="html">&lt;p&gt;My blog uses &lt;a class="reference external" href="http://docs.getpelican.com"&gt;Pelican&lt;/a&gt; a static website
generator. All my articles are under version control. To generate after each
modification the new html version of the pages, you must use the &lt;tt class="docutils literal"&gt;make
regenerate&lt;/tt&gt;. To launch the test web server, you use &lt;tt class="docutils literal"&gt;make serve&lt;/tt&gt;. Finally to
synchronize the content on the …&lt;/p&gt;</summary><content type="html">&lt;p&gt;My blog uses &lt;a class="reference external" href="http://docs.getpelican.com"&gt;Pelican&lt;/a&gt; a static website
generator. All my articles are under version control. To generate after each
modification the new html version of the pages, you must use the &lt;tt class="docutils literal"&gt;make
regenerate&lt;/tt&gt;. To launch the test web server, you use &lt;tt class="docutils literal"&gt;make serve&lt;/tt&gt;. Finally to
synchronize the content on the server, you use &lt;tt class="docutils literal"&gt;make rsync_upload&lt;/tt&gt;. Each time
I do this, I also push my modifications to my server and to &lt;a class="reference external" href="https://bitbucket.org/Jenselme/www.jujens.eu/overview"&gt;Bitbucket&lt;/a&gt; in order to have a
backup.&lt;/p&gt;
&lt;p&gt;Until now, I managed all that in a standard terminal. I already had a bash
function to switch to the proper directory and enable python's venv. However, I
did not find that very practical. &lt;tt class="docutils literal"&gt;make serve&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;make regenerate&lt;/tt&gt; must
always stay in background, I have to push to two different repositories and
synchronize with the server. So I decided to create a script to improve that.&lt;/p&gt;
&lt;p&gt;Since I need to launch the same commands in the same folder without leaving the
venv and since I want to easily interact with the background commands, I decided
to create a small shell. I am very happy with it.&lt;/p&gt;
&lt;p&gt;Some explanations on the script (available below):&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Everything is in an infinite loop to simulate a true shell. &lt;tt class="docutils literal"&gt;echo &lt;span class="pre"&gt;-ne&lt;/span&gt; &amp;quot;&amp;gt; &amp;quot;&lt;/tt&gt;
print a prompt and let the cursor on the same line.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;exec 3&amp;lt; &amp;lt;(make serve)&lt;/tt&gt;&lt;ul&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&amp;lt;(make serve)&lt;/tt&gt; is replaced by a path to a virtual file connected to the
standard output of the command.&lt;/li&gt;
&lt;li&gt;Since we want the process to be in background, we launch it with &lt;tt class="docutils literal"&gt;exec&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Finally, since we want to fetch the output of the command, we connect the
file to a new output named 3. We then read its content with &lt;tt class="docutils literal"&gt;cat
&amp;lt;&amp;amp;3&lt;/tt&gt;. &lt;strong&gt;While the file is not closed, this command won't stop.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Got to &lt;a class="reference external" href="http://stackoverflow.com/questions/20017805/bash-capture-output-of-command-run-in-background?answertab=active#tab-top"&gt;this thread&lt;/a&gt;
for more details.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Additional output: I tried to store the name of the ouputs in variables. That
would have allowed me to refactor and clarify the code. However, that makes
&lt;tt class="docutils literal"&gt;exec &lt;span class="pre"&gt;&amp;quot;${var}&amp;quot;&amp;lt;&lt;/span&gt; &amp;lt;(make serve)&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;cat &lt;span class="pre"&gt;&amp;lt;&amp;amp;&amp;quot;${var}&amp;quot;&lt;/span&gt;&lt;/tt&gt; crash.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;[ &lt;span class="pre"&gt;-n&lt;/span&gt; &lt;span class="pre"&gt;&amp;quot;${serve_pid}&amp;quot;&lt;/span&gt; ] &amp;amp;&amp;amp; has_died &lt;span class="pre"&gt;&amp;quot;${serve_pid}&amp;quot;&lt;/span&gt;&lt;/tt&gt;:
&lt;tt class="docutils literal"&gt;has_died&lt;/tt&gt; must not be surrounded by brackets (that means it must not be
pass to the &lt;tt class="docutils literal"&gt;test&lt;/tt&gt; command) in order for the script to work properly.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;echo ${pid}&lt;/tt&gt;: you can only send error code with &lt;tt class="docutils literal"&gt;return&lt;/tt&gt;. For everything
else, you must use &lt;tt class="docutils literal"&gt;echo&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You will find the whole script below. You can also &lt;a class="reference external" href="//www.jujens.eu/static/shell-pelican/blog.sh"&gt;download it&lt;/a&gt; ou le &lt;a class="reference external" href="https://github.com/Jenselme/dot-files-shell/blob/master/bin/blog.sh"&gt;see it on github&lt;/a&gt; if you
want the latest version&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ln"&gt;  1 &lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/bash
&lt;/span&gt;&lt;span class="ln"&gt;  2 &lt;/span&gt;&lt;span class="ch"&gt;&lt;/span&gt;
&lt;span class="ln"&gt;  3 &lt;/span&gt;stop_command&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt;  4 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt;  5 &lt;/span&gt;        &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;  6 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt;  7 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt;  8 &lt;/span&gt;
&lt;span class="ln"&gt;  9 &lt;/span&gt;has_died&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 10 &lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;kill&lt;/span&gt; -0 &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; /dev/null &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 11 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="ln"&gt; 12 &lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="ln"&gt; 13 &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="ln"&gt; 14 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 15 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 16 &lt;/span&gt;
&lt;span class="ln"&gt; 17 &lt;/span&gt;find_pid&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 18 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;ps -elf &lt;span class="p"&gt;|&lt;/span&gt; grep &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -v &lt;span class="s1"&gt;'&amp;amp;&amp;amp;'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -v &lt;span class="s1"&gt;'grep'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;'{print $4}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 19 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 20 &lt;/span&gt;
&lt;span class="ln"&gt; 21 &lt;/span&gt;get_pid&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="ln"&gt; 22 &lt;/span&gt;    &lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find_pid &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 23 &lt;/span&gt;    &lt;span class="k"&gt;until&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="ln"&gt; 24 &lt;/span&gt;        &lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;find_pid &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 25 &lt;/span&gt;    &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="ln"&gt; 26 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 27 &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="ln"&gt; 28 &lt;/span&gt;
&lt;span class="ln"&gt; 29 &lt;/span&gt;&lt;span class="c1"&gt;# Activate venv
&lt;/span&gt;&lt;span class="ln"&gt; 30 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/server/blog/
&lt;span class="ln"&gt; 31 &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; bin/activate
&lt;span class="ln"&gt; 32 &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; pelican/jujens.eu
&lt;span class="ln"&gt; 33 &lt;/span&gt;
&lt;span class="ln"&gt; 34 &lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 35 &lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 36 &lt;/span&gt;&lt;span class="c1"&gt;# These variables cannot be used. If you try to use them, you will get an error like 3&amp;lt; not found.
&lt;/span&gt;&lt;span class="ln"&gt; 37 &lt;/span&gt;&lt;span class="c1"&gt;#regenerate_output=3
&lt;/span&gt;&lt;span class="ln"&gt; 38 &lt;/span&gt;&lt;span class="c1"&gt;#serve_output=4
&lt;/span&gt;&lt;span class="ln"&gt; 39 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;
&lt;span class="ln"&gt; 40 &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; true&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="ln"&gt; 41 &lt;/span&gt;    &lt;span class="c1"&gt;# Print errors for regenerate
&lt;/span&gt;&lt;span class="ln"&gt; 42 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 43 &lt;/span&gt;        &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;Regenerate has died with ouput:\n&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 44 &lt;/span&gt;        cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="ln"&gt; 45 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 46 &lt;/span&gt;    &lt;span class="c1"&gt;# Print errors for serve
&lt;/span&gt;&lt;span class="ln"&gt; 47 &lt;/span&gt;&lt;span class="c1"&gt;&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 48 &lt;/span&gt;        &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;Serve has died with ouput:\n&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 49 &lt;/span&gt;        cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;span class="ln"&gt; 50 &lt;/span&gt;    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 51 &lt;/span&gt;
&lt;span class="ln"&gt; 52 &lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; -en &lt;span class="s2"&gt;&amp;quot;(blog) &amp;gt; &amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 53 &lt;/span&gt;    &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;span class="ln"&gt; 54 &lt;/span&gt;
&lt;span class="ln"&gt; 55 &lt;/span&gt;    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
&lt;span class="ln"&gt; 56 &lt;/span&gt;        deploy&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 57 &lt;/span&gt;            hg push &amp;gt; /dev/null
&lt;span class="ln"&gt; 58 &lt;/span&gt;            hg push bitbucket &amp;gt;/dev/null
&lt;span class="ln"&gt; 59 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 60 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 61 &lt;/span&gt;            &lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 62 &lt;/span&gt;            &lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt; 63 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &amp;gt; /dev/null &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="ln"&gt; 64 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &amp;gt; /dev/null &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="ln"&gt; 65 &lt;/span&gt;            make rsync_upload &amp;gt; /dev/null
&lt;span class="ln"&gt; 66 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 67 &lt;/span&gt;        push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 68 &lt;/span&gt;            hg push &amp;gt; /dev/null
&lt;span class="ln"&gt; 69 &lt;/span&gt;            hg push bitbucket &amp;gt; /dev/null
&lt;span class="ln"&gt; 70 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 71 &lt;/span&gt;        st&lt;span class="p"&gt;|&lt;/span&gt;status&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 72 &lt;/span&gt;            hg st
&lt;span class="ln"&gt; 73 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 74 &lt;/span&gt;        add&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 75 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Enter the filename to add (. for all files)&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 76 &lt;/span&gt;            &lt;span class="nb"&gt;read&lt;/span&gt; file_name
&lt;span class="ln"&gt; 77 &lt;/span&gt;            hg add &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;file_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 78 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 79 &lt;/span&gt;        ci&lt;span class="p"&gt;|&lt;/span&gt;commit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 80 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Please enter the commit message:&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 81 &lt;/span&gt;            &lt;span class="nb"&gt;read&lt;/span&gt; commit_msg
&lt;span class="ln"&gt; 82 &lt;/span&gt;            hg ci -m &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;commit_msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 83 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 84 &lt;/span&gt;        serve&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 85 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ! has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 86 &lt;/span&gt;                &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Serve is already running.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 87 &lt;/span&gt;            &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="ln"&gt; 88 &lt;/span&gt;                &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;make serve &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 89 &lt;/span&gt;                &lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_pid &lt;span class="s1"&gt;'python3 -m pelican.server'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 90 &lt;/span&gt;            &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 91 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt; 92 &lt;/span&gt;        regenerate&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 93 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ! has_died &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt; 94 &lt;/span&gt;                &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Regenerate is already running.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt; 95 &lt;/span&gt;            &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="ln"&gt; 96 &lt;/span&gt;                &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;make regenerate &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 97 &lt;/span&gt;                &lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;get_pid &lt;span class="s1"&gt;'make regenerate'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt; 98 &lt;/span&gt;            &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt; 99 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;100 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;stop serve&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;101 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;102 &lt;/span&gt;            &lt;span class="nv"&gt;serve_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt;103 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;104 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;105 &lt;/span&gt;        &lt;span class="s2"&gt;&amp;quot;stop regenerate&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;106 &lt;/span&gt;            stop_command &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;107 &lt;/span&gt;            &lt;span class="nv"&gt;regenerate_pid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="ln"&gt;108 &lt;/span&gt;            cat &amp;lt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &amp;gt; /dev/null
&lt;span class="ln"&gt;109 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;110 &lt;/span&gt;        stop&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;111 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Stop requires an argument: serve or regenerate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;112 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;113 &lt;/span&gt;        quit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;114 &lt;/span&gt;            &lt;span class="nb"&gt;break&lt;/span&gt;
&lt;span class="ln"&gt;115 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;116 &lt;/span&gt;        &lt;span class="nb"&gt;help&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;117 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Available commands:&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;118 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tdeploy&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;119 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tpush&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;120 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tserve&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;121 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tregenerate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;122 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tstop serve&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;123 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\tstop regenerate&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;124 &lt;/span&gt;            &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;\thelp&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;125 &lt;/span&gt;            &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="ln"&gt;126 &lt;/span&gt;        *&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="ln"&gt;127 &lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="ln"&gt;128 &lt;/span&gt;                &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;command&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is invalid.&amp;quot;&lt;/span&gt;
&lt;span class="ln"&gt;129 &lt;/span&gt;            &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="ln"&gt;130 &lt;/span&gt;    &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="ln"&gt;131 &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="ln"&gt;132 &lt;/span&gt;
&lt;span class="ln"&gt;133 &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Done&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="Bash/Shell"></category><category term="Linux"></category><category term="Pelican"></category></entry><entry><title>Use trap in Bash to trap signals</title><link href="//www.jujens.eu/posts/en/2015/Jan/09/utiliser-trap-bash/" rel="alternate"></link><published>2015-01-09T00:00:00+01:00</published><updated>2015-01-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-09:/posts/en/2015/Jan/09/utiliser-trap-bash/</id><summary type="html">&lt;p&gt;&lt;strong&gt;Update 2017-09-96:&lt;/strong&gt; add example to use the name of the signals. Thanks to &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-18"&gt;Thomas&lt;/a&gt; and &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-127"&gt;Lokta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bash can intercept signals send by some special keys like Ctrl-C and change
their default behaviour. In order to do that, you must use the &lt;tt class="docutils literal"&gt;trap&lt;/tt&gt;
command. This command take as argument the command …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;Update 2017-09-96:&lt;/strong&gt; add example to use the name of the signals. Thanks to &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-18"&gt;Thomas&lt;/a&gt; and &lt;a class="reference external" href="https://www.jujens.eu/posts/2015/Jan/09/utiliser-trap-bash/#isso-127"&gt;Lokta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bash can intercept signals send by some special keys like Ctrl-C and change
their default behaviour. In order to do that, you must use the &lt;tt class="docutils literal"&gt;trap&lt;/tt&gt;
command. This command take as argument the command you want to execute when the
signal is emitted and the list of signals you want to trap.&lt;/p&gt;
&lt;p&gt;For instance:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;echo yollo&amp;quot;&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;will print &lt;tt class="docutils literal"&gt;yollo&lt;/tt&gt; when &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Ctrl-C&lt;/span&gt;&lt;/tt&gt; is pressed.&lt;/p&gt;
&lt;p&gt;To get the list of all signals, with their numbers and their names, you can use
&lt;tt class="docutils literal"&gt;kill&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;kill&lt;/span&gt; -l
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGHUP       &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGINT       &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGQUIT      &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGILL
&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGTRAP      &lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGABRT      &lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGEMT       &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGFPE
&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;SIGKILL     &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGBUS      &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGSEGV     &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; SIGSYS
&lt;/pre&gt;
&lt;p&gt;To use the names of the signal instead, use:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;echo 'sig INT caught' &amp;quot;&lt;/span&gt; INT
&lt;/pre&gt;
&lt;p&gt;You can also use it to kill the children of a process with:&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;trap - SIGTERM &amp;amp;&amp;amp; kill -- -&lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; SIGINT SIGTERM EXIT
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Linux"></category><category term="Bash/Shell"></category></entry><entry><title>Utiliser un service webdav avec curl</title><link href="//www.jujens.eu/posts/2015/Jan/07/curl-webdav/" rel="alternate"></link><published>2015-01-07T00:00:00+01:00</published><updated>2015-01-07T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-07:/posts/2015/Jan/07/curl-webdav/</id><summary type="html">&lt;p&gt;Il est tout à fait possible (et c'est même facile) d'utiliser &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt; pour
communiquer avec un service webdav. Attention toute fois, tous les événements
sont contenus dans des fichiers séparés qui doivent contenir les lignes
&lt;tt class="docutils literal"&gt;BEGIN:VCALENDAR&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;END:VCALENDAR&lt;/tt&gt; en plus des lignes décrivant
l'évènement en lui même.&lt;/p&gt;
&lt;p&gt;Pour …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Il est tout à fait possible (et c'est même facile) d'utiliser &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt; pour
communiquer avec un service webdav. Attention toute fois, tous les événements
sont contenus dans des fichiers séparés qui doivent contenir les lignes
&lt;tt class="docutils literal"&gt;BEGIN:VCALENDAR&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;END:VCALENDAR&lt;/tt&gt; en plus des lignes décrivant
l'évènement en lui même.&lt;/p&gt;
&lt;p&gt;Pour recevoir la liste au format xml des événements, il suffit de faire :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
curl -k --user &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;login&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -X PROPFIND &lt;span class="s2"&gt;&amp;quot;https://owncloud.jujens.eu/remote.php/caldav/calendars/jujens/defaultcalendar&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour poster un nouvel événement ou mettre à jour un événement existant, il
suffit de faire une requête put à l'url du service complétée par un nom de
fichier. Si le fichier existe, on met à jour l'événement correspondant. Sinon on
en crée un nouveau.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
curl -k --user &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;login&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -X PUT -H &lt;span class="s2"&gt;&amp;quot;Content-Type: text/calendar; charset=utf-8&amp;quot;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://owncloud.jujens.eu/remote.php/caldav/calendars/jujens/omis/&amp;lt;mon-fichier.ics&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Idem pour la suppression :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
curl -k --user &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;login&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -X DELETE -H &lt;span class="s2"&gt;&amp;quot;Content-Type: text/calendar; charset=utf-8&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://owncloud.jujens.eu/remote.php/caldav/calendars/jujens/omis/&amp;lt;mon-fichier.ics&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Linux"></category><category term="Bash/Shell"></category><category term="Webdav"></category><category term="curl"></category></entry><entry><title>Use a webdav service with curl</title><link href="//www.jujens.eu/posts/en/2015/Jan/07/curl-webdav/" rel="alternate"></link><published>2015-01-07T00:00:00+01:00</published><updated>2015-01-07T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2015-01-07:/posts/en/2015/Jan/07/curl-webdav/</id><summary type="html">&lt;p&gt;It is really easy to use &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt; to communicate with a webdav service. You just
have to be aware that all events are contained in separate files and that the
lines describing the event must be surrounded by &lt;tt class="docutils literal"&gt;BEGIN:VCALENDAR&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;END:VCALENDAR&lt;/tt&gt; lines.&lt;/p&gt;
&lt;p&gt;To get the list of all …&lt;/p&gt;</summary><content type="html">&lt;p&gt;It is really easy to use &lt;tt class="docutils literal"&gt;curl&lt;/tt&gt; to communicate with a webdav service. You just
have to be aware that all events are contained in separate files and that the
lines describing the event must be surrounded by &lt;tt class="docutils literal"&gt;BEGIN:VCALENDAR&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;END:VCALENDAR&lt;/tt&gt; lines.&lt;/p&gt;
&lt;p&gt;To get the list of all events as an xml answer :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
curl -k --user &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;login&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -X PROPFIND &lt;span class="s2"&gt;&amp;quot;https://owncloud.jujens.eu/remote.php/caldav/calendars/jujens/defaultcalendar&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To post a new event or to update an existing event, simply do a put request to
your service url concatenated with a file name. If the file name is not already
used, you create a new event. Otherwise, you update the given event.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
curl -k --user &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;login&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -X PUT -H &lt;span class="s2"&gt;&amp;quot;Content-Type: text/calendar; charset=utf-8&amp;quot;&lt;/span&gt; -d &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://owncloud.jujens.eu/remote.php/caldav/calendars/jujens/omis/&amp;lt;mon-fichier.ics&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It is the same for the deletion (with a delete request):&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
curl -k --user &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;login&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; -X DELETE -H &lt;span class="s2"&gt;&amp;quot;Content-Type: text/calendar; charset=utf-8&amp;quot;&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://owncloud.jujens.eu/remote.php/caldav/calendars/jujens/omis/&amp;lt;mon-fichier.ics&amp;gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Linux"></category><category term="Bash/Shell"></category><category term="Webdav"></category><category term="curl"></category></entry><entry><title>Des modèles de business model canvas en français pour LibreOffice Impress</title><link href="//www.jujens.eu/posts/2014/Nov/22/business-model-canvas-impress/" rel="alternate"></link><published>2014-11-22T00:00:00+01:00</published><updated>2014-11-22T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-11-22:/posts/2014/Nov/22/business-model-canvas-impress/</id><summary type="html">&lt;p&gt;Je viens de traduire en français un modèle de business modèle canvas pour
LibreOffice Impress. Il est au format A0. Pour l'inclure dans un autre document,
je vous conseille de l'exporter au format SVG puis le l'inclure en tant
qu'image. J'ai tenté d'utiliser l'import OLE mais le document est toujours …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Je viens de traduire en français un modèle de business modèle canvas pour
LibreOffice Impress. Il est au format A0. Pour l'inclure dans un autre document,
je vous conseille de l'exporter au format SVG puis le l'inclure en tant
qu'image. J'ai tenté d'utiliser l'import OLE mais le document est toujours trop
gros.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/business_model_canvas_templates/BusinessModelCanvas.otp"&gt;Le template en anglais&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/business_model_canvas_templates/BusinessModelCanvas_edit.otp"&gt;Le template en anglais à éditer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/business_model_canvas_templates/BusinessModelCanvas_fr.otp"&gt;Le template en français&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="/static/business_model_canvas_templates/BusinessModelCanvas_fr_edit.otp"&gt;Le template en français à éditer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Les modèles dont le nom de fichier contient &lt;em&gt;edit&lt;/em&gt; ne contiennent pas les
descriptifs des sections et sont donc prêts à être remplis par vos soins.&lt;/p&gt;
&lt;p&gt;Le modèle original en anglais vient de
&lt;a class="reference external" href="http://thoughtsof.matthiasjuette.de/business-model-canvas-template/"&gt;http://thoughtsof.matthiasjuette.de/business-model-canvas-template/&lt;/a&gt;. Ils sont
tous publiés sous la licence &lt;a class="reference external" href="http://creativecommons.org/licenses/by-sa/3.0/"&gt;Creative Commons Share Alike&lt;/a&gt;.&lt;/p&gt;
</content><category term="Libreoffice"></category><category term="business model canvas"></category><category term="entreprenariat"></category><category term="création d'entreprise"></category></entry><entry><title>Utiliser AngularJS et Django pour faire des requêtes AJAX</title><link href="//www.jujens.eu/posts/2014/Oct/25/django-angularjs-ajax/" rel="alternate"></link><published>2014-10-25T00:00:00+02:00</published><updated>2014-10-25T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-10-25:/posts/2014/Oct/25/django-angularjs-ajax/</id><summary type="html">&lt;p&gt;Dans ce petit tuto, je vais vous expliquer comment faire pour poster un
formulaire Django via une requête AJAX en utilisant le framework JavaScript
AngularJS. Tout d'abord, il faut un peu de préparation. Voici le modèle que nous
allons utiliser (les imports ne sont pas précisés et je suppose que …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Dans ce petit tuto, je vais vous expliquer comment faire pour poster un
formulaire Django via une requête AJAX en utilisant le framework JavaScript
AngularJS. Tout d'abord, il faut un peu de préparation. Voici le modèle que nous
allons utiliser (les imports ne sont pas précisés et je suppose que vous savez
où mettre ces fichiers) :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto_now&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Category'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Le formulaire :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CardForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Card&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Le code de la vue :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CardForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FILES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleaned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleaned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CardForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'board/add_card.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et enfin le template :&lt;/p&gt;
&lt;pre class="code jinja literal-block"&gt;
&lt;span class="x"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;load&lt;/span&gt; &lt;span class="nv"&gt;staticfiles&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;
&amp;lt;html ng-app=&amp;quot;ajax&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;gt;
   &amp;lt;script src=&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;angular.js&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt; type=&amp;quot;text/javascript&amp;quot; &amp;gt;&amp;lt;/script&amp;gt;
   &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;angular-cookies.js&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;&amp;gt;&amp;lt;/script&amp;gt;
   &amp;lt;script src=&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;controllers.js&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt; type=&amp;quot;text/javascript&amp;quot; &amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;/head&amp;gt;
 &amp;lt;body&amp;gt;
&amp;lt;form action=&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;url&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;board.views.add_card&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;&amp;quot; ng-controller=&amp;quot;MyFormCtrl&amp;quot;
       method=&amp;quot;post&amp;quot; name=&amp;quot;form&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;csrf_token&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;
       &amp;lt;p&amp;gt;
         &amp;lt;label for=&amp;quot;id_content&amp;quot;&amp;gt;Content:&amp;lt;/label&amp;gt;
         &amp;lt;textarea cols=&amp;quot;40&amp;quot; id=&amp;quot;id_content&amp;quot; name=&amp;quot;content&amp;quot; rows=&amp;quot;10&amp;quot; ng-model=&amp;quot;card.content&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
       &amp;lt;/p&amp;gt;
         &amp;lt;p&amp;gt;&amp;lt;label for=&amp;quot;id_category&amp;quot;&amp;gt;Category:&amp;lt;/label&amp;gt; &amp;lt;select ng-model=&amp;quot;card.category&amp;quot; id=&amp;quot;id_category&amp;quot; name=&amp;quot;category&amp;quot;&amp;gt;
         &amp;lt;option value=&amp;quot;&amp;quot; selected=&amp;quot;selected&amp;quot;&amp;gt;---------&amp;lt;/option&amp;gt;
         &amp;lt;option value=&amp;quot;1&amp;quot;&amp;gt;Backlog&amp;lt;/option&amp;gt;
         &amp;lt;option value=&amp;quot;2&amp;quot;&amp;gt;Done&amp;lt;/option&amp;gt;
         &amp;lt;option value=&amp;quot;3&amp;quot;&amp;gt;In progress&amp;lt;/option&amp;gt;
         &amp;lt;/select&amp;gt;
         &amp;lt;button ng-click=&amp;quot;submit($event)&amp;quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
       &amp;lt;/p&amp;gt;
 &amp;lt;/form&amp;gt;
 &amp;lt;/body&amp;gt;
 &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Comme toute application Angular, il contient la balise &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-app&lt;/span&gt;&lt;/tt&gt; pour signaler
au framework qu'il s'agit une portion de HTML géré par Angular et une balise
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-controller&lt;/span&gt;&lt;/tt&gt; pour faire le lien avec le contrôleur de Angular. J'ai
également ajouté &lt;tt class="docutils literal"&gt;{% load staticfiles %}&lt;/tt&gt; pour utiliser la directive
&lt;tt class="docutils literal"&gt;static&lt;/tt&gt; de django.&lt;/p&gt;
&lt;p&gt;Le formulaire doit être présent en intégralité dans le template (on ne peut pas
utiliser &lt;tt class="docutils literal"&gt;{{ form.as_p }}&lt;/tt&gt;) pour pouvoir faire correctement les liens avec la
partie Angular :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;L'aire de texte avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-model=&amp;quot;card.content&amp;quot;&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;La liste d'option avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-model=&amp;quot;card.category&amp;quot;&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Le bouton de soumission avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-click=&amp;quot;submit($event)&amp;quot;&lt;/span&gt;&lt;/tt&gt;. Le &lt;tt class="docutils literal"&gt;$event&lt;/tt&gt; est
nécessaire pour éviter le rechargement de la page (voir le code JavaScript).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je vous laisse vous renseigner sur le fonctionnement d'Angular si vous n'êtes
pas familier avec celui-ci.&lt;/p&gt;
&lt;p&gt;Et pour finir, le code Javascript.&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;nameSpace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;trello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ngCookies'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;nameSpace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;MyFormCtrl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'$scope'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'$http'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'$cookies'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'application/x-www-form-urlencoded'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Pour envoyer le code csrf.
&lt;/span&gt;    &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'X-CSRFToken'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrftoken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Cette fonction est appelée quand on soumet le formulaire.
&lt;/span&gt;    &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// On évite le rechargement de la page.
&lt;/span&gt;        &lt;span class="nx"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// On prépare l'envoie des données.
&lt;/span&gt;        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'csrfmiddlewaretoken'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrftoken&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/add'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Remet le formulaire à zéro si tout c'est bien passé.
&lt;/span&gt;            &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}]);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Normalement le code est assez commenté pour que vous le compreniez. Au besoin,
postez un commentaire. Je signale juste que pour utiliser correctement le code
csrf (qui est stocké dans un cookie) il faut utiliser le plugin &lt;tt class="docutils literal"&gt;ngCookies&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Ce code dépend de jQuery. Je n'ai pas trouvé de méthode pour passer correctement
et facilement les paramètres de la requête avec uniquement Angular. La seule
méthode que j'ai est :&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'content='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;category='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;csrfmiddlewaretoken='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrftoken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note : la requête AJAX peut aussi se mettre sous la forme plus longue suivante :&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/add'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="Django"></category><category term="JavaScript"></category><category term="AJAX"></category><category term="AngularJS"></category></entry><entry><title>AJAX requests with Django and AngularJS</title><link href="//www.jujens.eu/posts/en/2014/Oct/25/django-angularjs-ajax/" rel="alternate"></link><published>2014-10-25T00:00:00+02:00</published><updated>2014-10-25T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-10-25:/posts/en/2014/Oct/25/django-angularjs-ajax/</id><summary type="html">&lt;p&gt;In this tutorial, I will explain how to submit a Django form with an AJAX
request thanks to AngularJS. First, we need to prepare our app - I don't precise
imports and I assume that you know in which file to write the code. First, the
model:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;In this tutorial, I will explain how to submit a Django form with an AJAX
request thanks to AngularJS. First, we need to prepare our app - I don't precise
imports and I assume that you know in which file to write the code. First, the
model:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateTimeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto_now_add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto_now&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Category'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The form:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CardForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;forms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelForm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Card&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The view:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CardForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FILES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleaned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cleaned_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CardForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'board/add_card.html'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And the template:&lt;/p&gt;
&lt;pre class="code jinja literal-block"&gt;
&lt;span class="x"&gt;&amp;lt;!DOCTYPE html&amp;gt;
&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;load&lt;/span&gt; &lt;span class="nv"&gt;staticfiles&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;
&amp;lt;html ng-app=&amp;quot;ajax&amp;quot;&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;gt;
   &amp;lt;script src=&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;angular.js&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt; type=&amp;quot;text/javascript&amp;quot; &amp;gt;&amp;lt;/script&amp;gt;
   &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;angular-cookies.js&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;&amp;gt;&amp;lt;/script&amp;gt;
   &amp;lt;script src=&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;controllers.js&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt; type=&amp;quot;text/javascript&amp;quot; &amp;gt;&amp;lt;/script&amp;gt;
 &amp;lt;/head&amp;gt;
 &amp;lt;body&amp;gt;
&amp;lt;form action=&amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;url&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;board.views.add_card&amp;quot;&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;&amp;quot; ng-controller=&amp;quot;MyFormCtrl&amp;quot;
       method=&amp;quot;post&amp;quot; name=&amp;quot;form&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;csrf_token&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;&lt;span class="x"&gt;
       &amp;lt;p&amp;gt;
         &amp;lt;label for=&amp;quot;id_content&amp;quot;&amp;gt;Content:&amp;lt;/label&amp;gt;
         &amp;lt;textarea cols=&amp;quot;40&amp;quot; id=&amp;quot;id_content&amp;quot; name=&amp;quot;content&amp;quot; rows=&amp;quot;10&amp;quot; ng-model=&amp;quot;card.content&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;
       &amp;lt;/p&amp;gt;
         &amp;lt;p&amp;gt;&amp;lt;label for=&amp;quot;id_category&amp;quot;&amp;gt;Category:&amp;lt;/label&amp;gt; &amp;lt;select ng-model=&amp;quot;card.category&amp;quot; id=&amp;quot;id_category&amp;quot; name=&amp;quot;category&amp;quot;&amp;gt;
         &amp;lt;option value=&amp;quot;&amp;quot; selected=&amp;quot;selected&amp;quot;&amp;gt;---------&amp;lt;/option&amp;gt;
         &amp;lt;option value=&amp;quot;1&amp;quot;&amp;gt;Backlog&amp;lt;/option&amp;gt;
         &amp;lt;option value=&amp;quot;2&amp;quot;&amp;gt;Done&amp;lt;/option&amp;gt;
         &amp;lt;option value=&amp;quot;3&amp;quot;&amp;gt;In progress&amp;lt;/option&amp;gt;
         &amp;lt;/select&amp;gt;
         &amp;lt;button ng-click=&amp;quot;submit($event)&amp;quot;&amp;gt;Submit&amp;lt;/button&amp;gt;
       &amp;lt;/p&amp;gt;
 &amp;lt;/form&amp;gt;
 &amp;lt;/body&amp;gt;
 &amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;As any Angular app, it contains a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-app&lt;/span&gt;&lt;/tt&gt; and a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-controllers&lt;/span&gt;&lt;/tt&gt; tags to
link your page with the JS code. I also added &lt;tt class="docutils literal"&gt;{% load staticfile %}&lt;/tt&gt; to use
django's &lt;tt class="docutils literal"&gt;static&lt;/tt&gt; directive.&lt;/p&gt;
&lt;p&gt;The form must be completely present in the template - you can't use &lt;tt class="docutils literal"&gt;{{
form.as_p }}&lt;/tt&gt; - in order to correctly map its element with the model in Angular:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The Textaera with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-model=&amp;quot;card.content&amp;quot;&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;The options with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-model=&amp;quot;card.category&amp;quot;&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;The submit button with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;ng-click=&amp;quot;submit($event)&amp;quot;&lt;/span&gt;&lt;/tt&gt;. &lt;tt class="docutils literal"&gt;$event&lt;/tt&gt; is required
to avoid a page reload when the form is submitted.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And now, the JS code:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;nameSpace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;trello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'ngCookies'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;nameSpace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;MyFormCtrl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'$scope'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'$http'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'$cookies'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'application/x-www-form-urlencoded'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// To send the csrf code.
&lt;/span&gt;    &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'X-CSRFToken'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrftoken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// This function is called when the form is submitted.
&lt;/span&gt;    &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Prevent page reload.
&lt;/span&gt;        &lt;span class="nx"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// Send the data.
&lt;/span&gt;        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'category'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'csrfmiddlewaretoken'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrftoken&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/add'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Reset the form in case of success.
&lt;/span&gt;            &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}]);&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In order to use the csrf code - which is stored in a cookie, you need to use the
&lt;tt class="docutils literal"&gt;ngCookie&lt;/tt&gt; plugin. You should be able to understand the rest of the code. In
case of trouble, leave a comment.&lt;/p&gt;
&lt;p&gt;This code requires jQuery. I have not found a way to correctly pass the argument
with just Angular. The only method I have is:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'content='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;category='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;csrfmiddlewaretoken='&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;$cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrftoken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note: The AJAX request can also be written like this:&lt;/p&gt;
&lt;pre class="code javascript literal-block"&gt;
&lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'/add'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;in_data&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="Django"></category><category term="JavaScript"></category><category term="AJAX"></category><category term="AngularJS"></category></entry><entry><title>Installer des paquets npm sans les droits root</title><link href="//www.jujens.eu/posts/2014/Oct/24/install-npm-packages-as-user/" rel="alternate"></link><published>2014-10-24T00:00:00+02:00</published><updated>2014-10-24T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-10-24:/posts/2014/Oct/24/install-npm-packages-as-user/</id><summary type="html">&lt;p&gt;&lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; peut soit installer un paquet dans le dossier du projet courant soit de
façon globale pour tous les projets avec l'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-g&lt;/span&gt;&lt;/tt&gt;. Par défaut dans ce
mode, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; installe les paquets dans &lt;tt class="docutils literal"&gt;/usr/lib/node_module&lt;/tt&gt; ce qui
nécessite les droits root. En dehors du désagrément que cela procure, cela …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; peut soit installer un paquet dans le dossier du projet courant soit de
façon globale pour tous les projets avec l'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-g&lt;/span&gt;&lt;/tt&gt;. Par défaut dans ce
mode, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; installe les paquets dans &lt;tt class="docutils literal"&gt;/usr/lib/node_module&lt;/tt&gt; ce qui
nécessite les droits root. En dehors du désagrément que cela procure, cela peut
être dangereux si on installe un paquet depuis une source inconnue.&lt;/p&gt;
&lt;p&gt;Heureusement, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; peut aussi installer les paquets dans le home de
l'utilisateur courant. Pour cela, il faut tout d'abord créer le dossier qui
contiendra les paquets :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mkdir -p ~/.npm-packages
&lt;/pre&gt;
&lt;p&gt;Reste à configurer le préfixe de &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; (c'est là qu'il installe ces paquets)
avec la variable &lt;tt class="docutils literal"&gt;prefix&lt;/tt&gt; dans le &lt;tt class="docutils literal"&gt;.npmrc&lt;/tt&gt;. Ajoutez donc &lt;tt class="docutils literal"&gt;prefix =
&lt;span class="pre"&gt;/home/username/.npm-packages&lt;/span&gt;&lt;/tt&gt; à votre npmrc (&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.npmrc&lt;/span&gt;&lt;/tt&gt;).&lt;/p&gt;
&lt;p&gt;Il faut ensuite que votre shell ait les bonnes variables d'environnement. Pour
cela, ajoutez à votre .zshrc ou .bashrc :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# NPM
&lt;/span&gt;&lt;span class="nv"&gt;NPM_PACKAGES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.npm-packages&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# Pour que npm trouve ces paquets.
&lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NPM_PACKAGES&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# Pour que les scripts puissent être lancés directement depuis le terminal.
&lt;/span&gt;&lt;span class="nb"&gt;unset&lt;/span&gt; MANPATH
&lt;span class="nv"&gt;MANPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NPM_PACKAGES&lt;/span&gt;&lt;span class="s2"&gt;/share/man:&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;manpath&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# Pour que man trouve les manuels des commandes.
&lt;/span&gt;&lt;span class="nv"&gt;NODE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NPM_PACKAGES&lt;/span&gt;&lt;span class="s2"&gt;/lib/node_modules:&lt;/span&gt;&lt;span class="nv"&gt;$NODE_PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# Pour que node trouve les paquets.
&lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; NPM_PACKAGES PATH MANPATH NODE_PATH
&lt;/pre&gt;
&lt;p&gt;C'est fini. Maintenant, &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;-g&lt;/span&gt; bower&lt;/tt&gt; installera &lt;tt class="docutils literal"&gt;bower&lt;/tt&gt; dans votre
home sans les droits root.&lt;/p&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category><category term="npm"></category></entry><entry><title>Install npm packages with non root user</title><link href="//www.jujens.eu/posts/en/2014/Oct/24/install-npm-packages-as-user/" rel="alternate"></link><published>2014-10-24T00:00:00+02:00</published><updated>2014-10-24T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-10-24:/posts/en/2014/Oct/24/install-npm-packages-as-user/</id><summary type="html">&lt;p&gt;&lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; can install packages either in the current folder or globally with the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-g&lt;/span&gt;&lt;/tt&gt; option. By default, in this mode, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; installs packages in
&lt;tt class="docutils literal"&gt;/usr/lib/node_mudole&lt;/tt&gt;. You must be root to do this and it can be very
dangerous if you are installing an untrusted package.&lt;/p&gt;
&lt;p&gt;However, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; can …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; can install packages either in the current folder or globally with the
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-g&lt;/span&gt;&lt;/tt&gt; option. By default, in this mode, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; installs packages in
&lt;tt class="docutils literal"&gt;/usr/lib/node_mudole&lt;/tt&gt;. You must be root to do this and it can be very
dangerous if you are installing an untrusted package.&lt;/p&gt;
&lt;p&gt;However, &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; can also install packages in your home. To do this, you must
first create the folder which will contain all your packages :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mkdir -p ~/.npm-packages
&lt;/pre&gt;
&lt;p&gt;You must then configure the prefix - where &lt;tt class="docutils literal"&gt;npm&lt;/tt&gt; installs its packages - with
the &lt;tt class="docutils literal"&gt;prefix&lt;/tt&gt; variable in &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.npmrc&lt;/span&gt;&lt;/tt&gt;. So add &lt;tt class="docutils literal"&gt;prefix =
&lt;span class="pre"&gt;/home/username/.npm-packages&lt;/span&gt;&lt;/tt&gt; &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.npmrc&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Your shell must then have the proper environment variables. So add to your.zshrc
or .bashrc :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# NPM
&lt;/span&gt;&lt;span class="nv"&gt;NPM_PACKAGES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.npm-packages&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# So that npm finds its packages.
&lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NPM_PACKAGES&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# To launch script directly from the shell.
&lt;/span&gt;&lt;span class="nb"&gt;unset&lt;/span&gt; MANPATH
&lt;span class="nv"&gt;MANPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NPM_PACKAGES&lt;/span&gt;&lt;span class="s2"&gt;/share/man:&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;manpath&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# So that man finds the manpages.
&lt;/span&gt;&lt;span class="nv"&gt;NODE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$NPM_PACKAGES&lt;/span&gt;&lt;span class="s2"&gt;/lib/node_modules:&lt;/span&gt;&lt;span class="nv"&gt;$NODE_PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;# So that node finds these packages.
&lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt; NPM_PACKAGES PATH MANPATH NODE_PATH
&lt;/pre&gt;
&lt;p&gt;That's all. Now &lt;tt class="docutils literal"&gt;npm install &lt;span class="pre"&gt;-g&lt;/span&gt; bower&lt;/tt&gt; will install &lt;tt class="docutils literal"&gt;bower&lt;/tt&gt; in your home
without the need to be root!&lt;/p&gt;
</content><category term="Programmation"></category><category term="JavaScript"></category><category term="npm"></category></entry><entry><title>Utiliser git pour gérer les fichiers de configuration de son HOME</title><link href="//www.jujens.eu/posts/2014/Sep/09/home-git/" rel="alternate"></link><published>2014-09-09T00:00:00+02:00</published><updated>2014-09-09T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-09-09:/posts/2014/Sep/09/home-git/</id><summary type="html">&lt;p&gt;Depuis pas mal de temps, je gère les fichiers de conf de mon home avec git,
notamment ma conf emacs et mon dossier bin. L'intérêt étant à la fois de pouvoir
partager les configurations entre plusieurs ordinateurs, de pouvoir revenir en
arrière en cas de besoin et de voir l'historique …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Depuis pas mal de temps, je gère les fichiers de conf de mon home avec git,
notamment ma conf emacs et mon dossier bin. L'intérêt étant à la fois de pouvoir
partager les configurations entre plusieurs ordinateurs, de pouvoir revenir en
arrière en cas de besoin et de voir l'historique (surtout pour emacs).&lt;/p&gt;
&lt;p&gt;Je faisais ça à la main, avec un dépôt git tout simple. Puis, suite à lecture de
&lt;a class="reference external" href="http://blog.olivierdelort.net/?p=1261"&gt;cet article&lt;/a&gt;, j'ai décidé de passer à
vcsh et mr.&lt;/p&gt;
&lt;div class="section" id="vcsh-version-control-system-for-home"&gt;
&lt;h2&gt;VCSH – Version Control System for $HOME&lt;/h2&gt;
&lt;p&gt;L'intérêt de ce logiciel est qu'il vous permet de faire cohabiter plusieurs
dépôts git dans un même dossier. Ainsi vous pouvez facilement avoir un dépôt git
par catégorie de logiciel : un pour emacs, un pour votre bin, un autre pour zsh, …&lt;/p&gt;
&lt;p&gt;Par défaut, tous les dépôts sont dans &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.config/vcsh/repos.d&lt;/span&gt;&lt;/tt&gt;. Évidemment ça
se paramètre, voir la &lt;a class="reference external" href="https://github.com/RichiH/vcsh"&gt;page du projet sur github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Normalement, vous pouvez installer vcsh depuis les dépôts de votre
distribution.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="mr-myrepo"&gt;
&lt;h2&gt;mr — myrepo&lt;/h2&gt;
&lt;p&gt;mr est le compagnon de vcsh puisqu'il vous permet en une seule commande d'agir
sur plusieurs dépôts. Ainsi, pour pusher ou puller les modifications de tous les
dépôts sur un serveur il suffit de faire &lt;tt class="docutils literal"&gt;mr push&lt;/tt&gt; ou &lt;tt class="docutils literal"&gt;mr checkout&lt;/tt&gt;. Il
permet aussi de gérer la configuration des dépôts (sur quels url pusher
les modifications, sur votre serveur perso et sur github par exemple).&lt;/p&gt;
&lt;p&gt;Une fois de plus, le logiciel devrait être dans les dépôts de votre
distribution. Plus d'infos &lt;a class="reference external" href="http://myrepos.branchable.com/"&gt;ici&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="mettre-en-place-vcsh"&gt;
&lt;h2&gt;Mettre en place vcsh&lt;/h2&gt;
&lt;p&gt;Vous devez tout d'abord identifier comment vous désirez organiser vos
dépôts. Personnellement, je me suis organisé comme suis (les liens pointent sur
github) :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/Jenselme/dot-files-dcvs"&gt;dvcs&lt;/a&gt; pour les configurations
de git, mercurial et mr&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/Jenselme/dot-files-emacs"&gt;emacs&lt;/a&gt; pour la configuration d'Emacs&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/Jenselme/dot-files-shell"&gt;shell&lt;/a&gt; pour mon bin/ et les aliases + fonction&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/Jenselme/dot-files-zsh"&gt;zsh&lt;/a&gt; pour la configuration de
zsh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour initialiser un nouveau dépôt, rien de très compliqué :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# Initialisation du dépôt
&lt;/span&gt;vcsh init emacs
&lt;span class="c1"&gt;# Création du gitignore pour éviter d'avoir des erreures sur les dossiers non #suivi.
# Met simplement * dans le fichier.
&lt;/span&gt;vcsh write-gitignore emacs
&lt;span class="c1"&gt;# Ajout des fichiers
&lt;/span&gt;vcsh emacs add -f ~/.emacs ~/.emacs.d ~/.gitignore.d/emacs
vcsh emacs commit -am &lt;span class="s1"&gt;'intial commit'&lt;/span&gt;
vcsh emacs remote set-url --add origin git&amp;#64;github.com:Jenselme/dot-files-emacs.git
&lt;/pre&gt;
&lt;p&gt;Il peut être intéressant de personnaliser son .gitignore (qui de base est un peu
violent), surtout pour des configurations auxquelles on ajoute des fichiers
(comme celle d'emacs). Pour cela, il faut utiliser le ! pour inclure un sous
chemin exclu. Par exemple avec mon ~/.gitignore.d/emacs (le / représente la
racine du dépôt) :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
/*
!/.emacs
!/.emacs.d
*.elc
*~
/.emacs.d/session*
/.emacs.d/tramp
.emacs.d/url
.emacs.d/semanticdb/*
&lt;span class="se"&gt;\#&lt;/span&gt;*
.emacs.d/*.dat
.emacs.d/*.lst
&lt;/pre&gt;
&lt;p&gt;Je signale que si vous omettez le nom du dépôt pour une commande vcsh, alors
elle s'appliquera à tous. Particulièrement utile si vous voulez connaître le
statut de tous vos dépôts.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-mr"&gt;
&lt;h2&gt;Configurer mr&lt;/h2&gt;
&lt;p&gt;La configuration de mr se place dans &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;~/.mrconfig&lt;/span&gt;&lt;/tt&gt;. Ma configuration permet de
pusher mes dépôts à la fois sur mon serveur perso et sur github (pour
partager). Je la présente en intégralité et je vous laisse vous en inspirer pour
la vôtre.&lt;/p&gt;
&lt;pre class="code ini literal-block"&gt;
&lt;span class="k"&gt;[DEFAULT]&lt;/span&gt;
&lt;span class="na"&gt;git_gc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;git gc &amp;quot;$&amp;#64;&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;[$HOME/.config/vcsh/repo.d/emacs.git]&lt;/span&gt;
&lt;span class="na"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh clone --recursive ssh://git&amp;#64;jujens.eu/home/git/emacs.git emacs
  vcsh emacs remote add github git&amp;#64;github.com:Jenselme/dot-files-emacs.git&lt;/span&gt;

&lt;span class="na"&gt;push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh emacs push
  vcsh emacs push github&lt;/span&gt;

&lt;span class="k"&gt;[$HOME/.config/vcsh/repo.d/zsh.git]&lt;/span&gt;
&lt;span class="na"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh clone ssh://git&amp;#64;jujens.eu/home/git/zsh.git zsh
  vcsh zsh remote add github git&amp;#64;github.com:Jenselme/dot-files-zsh.git&lt;/span&gt;

&lt;span class="na"&gt;push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh zsh push
  vcsh zsh push github&lt;/span&gt;

&lt;span class="k"&gt;[$HOME/.config/vcsh/repo.d/dcvs.git]&lt;/span&gt;
&lt;span class="na"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh clone ssh://git&amp;#64;jujens.eu/home/git/dcvs.git dcvs
  vcsh dcvs remote add github git&amp;#64;github.com:Jenselme/dot-files-dcvs.git&lt;/span&gt;

&lt;span class="na"&gt;push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh dcvs push
  vcsh dcvs push github&lt;/span&gt;

&lt;span class="k"&gt;[$HOME/.config/vcsh/repo.d/shell.git]&lt;/span&gt;
&lt;span class="na"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh clone ssh://git&amp;#64;jujens.eu/home/git/shell.git shell
  vcsh shell remote add github git&amp;#64;github.com:Jenselme/dot-files-shell.git&lt;/span&gt;

&lt;span class="na"&gt;push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;
  vcsh shell push
  vcsh shell push github&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="recuperer-la-configuration"&gt;
&lt;h2&gt;Récupérer la configuration&lt;/h2&gt;
&lt;p&gt;Si vous arrivez sur une nouvelle machine, vous n'avez plus qu'à installer mr et
vcsh et cloner le dépôt contenant la configuration de mr.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
vcsh clone ssh://git&amp;#64;jujens.eu/home/git/dcvs.git dcvs
mr checkout
&lt;/pre&gt;
&lt;p&gt;Pour mettre à jour tous ces dépôts, un petit &lt;tt class="docutils literal"&gt;mr update&lt;/tt&gt; suffit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Le duo vcsh + mr est simple et efficace pour partager ses configurations entre
plusieurs ordinateurs.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="git"></category><category term="Linux"></category><category term="mr"></category><category term="vcsh"></category></entry><entry><title>Divers astuces en Shell</title><link href="//www.jujens.eu/posts/2014/Sep/07/diverses-astuces-shell/" rel="alternate"></link><published>2014-09-07T00:00:00+02:00</published><updated>2015-02-20T22:53:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-09-07:/posts/2014/Sep/07/diverses-astuces-shell/</id><summary type="html">&lt;p&gt;Liste de commandes pour des actions spécifiques. Pas/peu de
détails/explications, prérequis de shell supposés connus. Si une commande est
donnée pour bash uniquement, cela signifie qu’elle n’est pas compatible avec le
shell POSIX ou d’autres implémentations basiques mais est vraisemblablement
disponible dans les autres implémentations …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Liste de commandes pour des actions spécifiques. Pas/peu de
détails/explications, prérequis de shell supposés connus. Si une commande est
donnée pour bash uniquement, cela signifie qu’elle n’est pas compatible avec le
shell POSIX ou d’autres implémentations basiques mais est vraisemblablement
disponible dans les autres implémentations évoluées telles que zsh.&lt;/p&gt;
&lt;p&gt;J'ai initialement publié ce document &lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/wiki/Shell_secours"&gt;ici&lt;/a&gt;. Ce
document se veut un peu plus complet et ne contient pas de rappels de commandes
élémentaires comme &lt;tt class="docutils literal"&gt;wc&lt;/tt&gt;. J'ai également écrit un &lt;a class="reference external" href="/posts/2014/Sep/07/petit-precis-shell/"&gt;tutoriel sur le shell&lt;/a&gt;.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;&lt;strong&gt;Sommaire&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#corriger-le-caractere-de-fin-de-ligne" id="id1"&gt;Corriger le caractère de fin de ligne&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#enlever-les-shebang-de-plusieurs-fichiers" id="id2"&gt;Enlever les shebang de plusieurs fichiers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#operations-avancees-sur-les-variables" id="id3"&gt;Opérations avancées sur les variables&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#valeurs-par-defaut" id="id4"&gt;Valeurs par défaut&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#travailler-avec-les-chemins" id="id5"&gt;Travailler avec les chemins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#manipulation-avancee-de-chaines-de-caracteres" id="id6"&gt;Manipulation avancée de chaînes de caractères&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#extraire-une-sous-chaine-bash-uniquement" id="id7"&gt;Extraire une sous-chaîne (bash uniquement)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#remplacer-une-sous-chaine-par-une-autre-bash-uniquement" id="id8"&gt;Remplacer une sous-chaîne par une autre (bash uniquement)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#passer-du-texte-en-majuscule-minuscule-bash-uniquement" id="id9"&gt;Passer du texte en majuscule/minuscule (bash uniquement)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#supprimer-une-partie-de-chaine" id="id10"&gt;Supprimer une partie de chaîne&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-des-nombres-aleatoires" id="id11"&gt;Générer des nombres aléatoires&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#savoir-si-une-chaine-est-contenue-dans-une-autre" id="id12"&gt;Savoir si une chaîne est contenue dans une autre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#renommer-les-fichiers-en-fonction-dune-expression-reguliere" id="id13"&gt;Renommer les fichiers en fonction d’une expression régulière&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#savoir-si-un-script-est-lance-dans-un-shell-interactif" id="id14"&gt;Savoir si un script est lancé dans un shell interactif&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#chmod-a-x" id="id15"&gt;Chmod a+X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#differences-entre-les-implementations-de-certaines-commandes-entre-gnu-et-bsd" id="id16"&gt;Différences entre les implémentations de certaines commandes entre GNU et BSD&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#sed" id="id17"&gt;sed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="corriger-le-caractere-de-fin-de-ligne"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Corriger le caractère de fin de ligne&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Pour changer les caractères de fin de ligne d'un fichier de &lt;tt class="docutils literal"&gt;\r\n&lt;/tt&gt; (windows) à
&lt;tt class="docutils literal"&gt;\n&lt;/tt&gt; (Unix), (l'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-i&lt;/span&gt;&lt;/tt&gt; fait en sorte que la modification se fasse dans
le même fichier).&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
sed -i &lt;span class="s1"&gt;'s/\r$//'&lt;/span&gt; file
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="enlever-les-shebang-de-plusieurs-fichiers"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Enlever les shebang de plusieurs fichiers&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="c1"&gt;# Remove shebang
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; lib in &lt;span class="nv"&gt;$RPM_BUILD_ROOT&lt;/span&gt;/svgwrite/*.py&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  sed -i &lt;span class="s1"&gt;'1{\&amp;#64;^#!/usr/bin/env python&amp;#64;d}'&lt;/span&gt; &lt;span class="nv"&gt;$lib&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="operations-avancees-sur-les-variables"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Opérations avancées sur les variables&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="valeurs-par-defaut"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Valeurs par défaut&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Il est tout à fait possible de donner une valeur par défaut à une variable en
bash. Ainsi, le code suivant : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;FOO=${FOO:-coucou}&lt;/span&gt;&lt;/tt&gt; signifie que :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Si la variable FOO est définie, alors ne rien faire&lt;/li&gt;
&lt;li&gt;Si FOO n’est pas définie, alors FOO vaut &lt;em&gt;coucou&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cela fonctionne aussi avec une autre variable : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;FOO=${toto:-coucou}&lt;/span&gt;&lt;/tt&gt;. Cette
fois, FOO prendra la valeur &lt;em&gt;coucou&lt;/em&gt; si toto n’est pas définie. Cette forme
laisse toto inchangée. Pour affecter &lt;em&gt;coucou&lt;/em&gt; a foo et toto :
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;FOO=${toto:=coucou}&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="travailler-avec-les-chemins"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Travailler avec les chemins&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Le shell dispose de moyen de travailler avec les chemins de façon facile et
agréable :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Supprimer le dernier / : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${a%/}&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Supprimer le premier / : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${#*/}&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Récupérer le dossier courant : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${a##*/}&lt;/span&gt;&lt;/tt&gt; (si a ne se termine pas par /)&lt;/li&gt;
&lt;li&gt;Récupérer le dossier parent : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${a%/*}&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;En vérité, vous pouvez remplacer le / par n'importe quel autre caractère (un
point par exemple). Voir &lt;a class="reference internal" href="#supprimer-une-partie-de-chaine"&gt;supprimer une partie de chaîne&lt;/a&gt; pour plus de
détails.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="manipulation-avancee-de-chaines-de-caracteres"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Manipulation avancée de chaînes de caractères&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="extraire-une-sous-chaine-bash-uniquement"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Extraire une sous-chaîne (bash uniquement)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Simplement avec la syntaxe &lt;tt class="docutils literal"&gt;${chaine:début:longueur}&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;chaine&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Trucs et astuces en shell&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;chaine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;16&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Affiche &amp;quot;Trucs et astuces&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ou avec &lt;tt class="docutils literal"&gt;cut&lt;/tt&gt; :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
cut -cN-M &lt;span class="c1"&gt;# N : position du début, M : position de la fin&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="remplacer-une-sous-chaine-par-une-autre-bash-uniquement"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id8"&gt;Remplacer une sous-chaîne par une autre (bash uniquement)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On peut remplace la première occurrence uniquement :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;chaine_de_base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;J'aime les pommes et les framboises&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;remplacer_pomme_par&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fraises&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;chaine_corrigee&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;chaine_de_base&lt;/span&gt;&lt;span class="p"&gt;/pommes/&lt;/span&gt;&lt;span class="nv"&gt;$remplacer_pomme_par&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut aussi remplacer toutes les occurrences avec :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;chaine_corrigee&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;chaine_de_base&lt;/span&gt;&lt;span class="p"&gt;//pommes/&lt;/span&gt;&lt;span class="nv"&gt;$remplacer_pomme_par&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut aussi remplacer le début ou la fin :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/root/script.py&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="p"&gt;/#&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="nv"&gt;root&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="nv"&gt;tmp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="p"&gt;/%.*/.sh&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Ce qui donne :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
/tmp/script.py
/root/script.sh
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="passer-du-texte-en-majuscule-minuscule-bash-uniquement"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id9"&gt;Passer du texte en majuscule/minuscule (bash uniquement)&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;COUCOU
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# affiche &amp;quot;coucou&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;coucou
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;^^&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# affiche &amp;quot;COUCOU&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut aussi passer juste la première lettre en majuscule/minuscule :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;coucou
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# affiche &amp;quot;Coucou&amp;quot;
&lt;/span&gt;
&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Coucou
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# affiche &amp;quot;coucou&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="supprimer-une-partie-de-chaine"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id10"&gt;Supprimer une partie de chaîne&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pour supprimer la plus courte partie d'une string en partant du début, il suffit
d'utiliser la syntaxe &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${chaine#sous-chaine}&lt;/span&gt;&lt;/tt&gt;. Pour partir de la fin :
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${chaine%sous-chaine}&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/var/tmp/&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="p"&gt;#*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Affiche &amp;quot;var/tmp/&amp;quot;
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="p"&gt;%/*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Affiche &amp;quot;/var/tmp&amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour supprimer la plus longue partie possible d'une chaîne, il suffit de doubler
le caractère :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/var/tmp/toto&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="p"&gt;##*/&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Affiche toto
&lt;/span&gt;
&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;var/tmp/toto
&lt;span class="nb"&gt;echo&lt;/span&gt;  &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fichier&lt;/span&gt;&lt;span class="p"&gt;%%/*&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Affiche var&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="generer-des-nombres-aleatoires"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id11"&gt;Générer des nombres aléatoires&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Tire un nombre aléatoirement entre 0 - 32767 (bash uniquement) :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;$RANDOM&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Si RANDOM n’est pas disponible, la commande fortune qui tire aléatoirement un
proverbe l’est peut être. On en prend la somme pour obtenir un nombre.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
fortune &lt;span class="p"&gt;|&lt;/span&gt; cksum &lt;span class="p"&gt;|&lt;/span&gt; cut -f1 -d&lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Utilise la date où le PID du dernier processus.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;seed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$$&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; ps &lt;span class="p"&gt;;&lt;/span&gt; w &lt;span class="p"&gt;;&lt;/span&gt; date &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; cksum &lt;span class="o"&gt;|&lt;/span&gt; cut &lt;span class="o"&gt;-&lt;/span&gt;f1 &lt;span class="o"&gt;-&lt;/span&gt;d&lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Utilise l’entrée d’entropie du noyau. C’est la meilleur méthode, la plus
robuste pour générer de l’aléatoire.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/urandom &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt; /dev/null &lt;span class="p"&gt;|&lt;/span&gt; cksum &lt;span class="p"&gt;|&lt;/span&gt; cut -f1 -d&lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="savoir-si-une-chaine-est-contenue-dans-une-autre"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id12"&gt;Savoir si une chaîne est contenue dans une autre&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Avec la fonction test (&lt;strong&gt;bash uniquement&lt;/strong&gt;)&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;reg_exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ contenant &lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Avec grep&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
grep -q &lt;span class="s2"&gt;&amp;quot;reg_exp&amp;quot;&lt;/span&gt; chaine
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="renommer-les-fichiers-en-fonction-dune-expression-reguliere"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id13"&gt;Renommer les fichiers en fonction d’une expression régulière&lt;/a&gt;&lt;/h2&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; file in &lt;span class="sb"&gt;`&lt;/span&gt;ls&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;new_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;'s/\(.*\)\.dump\(.*\)\.sql/\2.\1.sql/'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
  mv &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="nv"&gt;$new_name&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut également utiliser Emacs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="savoir-si-un-script-est-lance-dans-un-shell-interactif"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id14"&gt;Savoir si un script est lancé dans un shell interactif&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;La commande &lt;tt class="docutils literal"&gt;tty &lt;span class="pre"&gt;-s&lt;/span&gt;&lt;/tt&gt; renvoie 0 si le script est lancé dans un terminal
interactif et 1 sinon.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="chmod-a-x"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id15"&gt;Chmod a+X&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;cite&gt;chmod a+X&lt;/cite&gt; va donner les droits d'exécution à un fichier uniquement si les
droits d'exécution sont présents pour l'utilisateur, le groupe ou tous. Par
exemple :&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
$ mkdir test
$ mkdir test/folder
$ mkdir -m 600 test/weired_folder
$ touch test/script
$ chmod +x test/script
$ touch test/file
&lt;/pre&gt;
&lt;p&gt;Les droits sont donc :&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
-rw-r--r--.  1 jenselme jenselme   0 Feb 20 23:02 file
drwxr-xr-x.  2 jenselme jenselme  40 Feb 20 23:01 folder
-rwxr-xr-x.  1 jenselme jenselme   0 Feb 20 23:02 script
drw-------.  2 jenselme jenselme  40 Feb 20 23:02 weired_folder
&lt;/pre&gt;
&lt;pre class="code literal-block"&gt;
$ chmod -R a+X
&lt;/pre&gt;
&lt;p&gt;Maintenant les droits sont :&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
-rw-r--r--.  1 jenselme jenselme   0 Feb 20 23:02 file
drwxr-xr-x.  2 jenselme jenselme  40 Feb 20 23:01 folder
-rwxr-xr-x.  1 jenselme jenselme   0 Feb 20 23:02 script
drwx--x--x.  2 jenselme jenselme  40 Feb 20 23:02 weired_folder
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="differences-entre-les-implementations-de-certaines-commandes-entre-gnu-et-bsd"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id16"&gt;Différences entre les implémentations de certaines commandes entre GNU et BSD&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="sed"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id17"&gt;sed&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;La commande &lt;tt class="docutils literal"&gt;sed&lt;/tt&gt; de BSD ne connaît pas certains métacaractères tels
que &lt;tt class="docutils literal"&gt;\s&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Les opérations dans un fichier se font :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;sed &lt;span class="pre"&gt;-i''&lt;/span&gt; 's/toto/tata/g' fichier&lt;/tt&gt; sous GNU mais&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;sed &lt;span class="pre"&gt;-i&lt;/span&gt; '' 's/toto/tata/g' fichier&lt;/tt&gt; sous BSD. La commande&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;sed &lt;span class="pre"&gt;-i&lt;/span&gt; &lt;span class="pre"&gt;-e&lt;/span&gt; s/toto/tata/g' fichier&lt;/tt&gt; est compatible avec les deux versions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Bash/Shell"></category><category term="Unix"></category></entry><entry><title>Petit précis de shell</title><link href="//www.jujens.eu/posts/2014/Sep/07/petit-precis-shell/" rel="alternate"></link><published>2014-09-07T00:00:00+02:00</published><updated>2014-10-05T14:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-09-07:/posts/2014/Sep/07/petit-precis-shell/</id><summary type="html">&lt;p&gt;Le shell (POSIX, ie sans les améliorations de Bash ou zsh) est un langage assez
particulier qu’on ne connaît pas forcément.  Le but de ce document est de
rappeler (ou donner) quelques bases du langage, de rappeler les différences
notables avec bash. Je propose dans un &lt;a class="reference external" href="/posts/2014/Sep/07/diverses-astuces-shell/"&gt;autre article&lt;/a&gt; quelques …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Le shell (POSIX, ie sans les améliorations de Bash ou zsh) est un langage assez
particulier qu’on ne connaît pas forcément.  Le but de ce document est de
rappeler (ou donner) quelques bases du langage, de rappeler les différences
notables avec bash. Je propose dans un &lt;a class="reference external" href="/posts/2014/Sep/07/diverses-astuces-shell/"&gt;autre article&lt;/a&gt; quelques solutions standards afin
de vous aider dans vos scripts. Ce document ne se veut en aucun cas un
cours/tuto complet et exhaustif. Des bases de shell et d’un autre langage de
programmation peuvent s’avérer utile. &lt;a class="reference external" href="http://www.siteduzero.com/informatique/tutoriels/reprenez-le-controle-a-l-aide-de-linux"&gt;Voir le site du zéros&lt;/a&gt;
pour un tuto orienté vers les débutants.&lt;/p&gt;
&lt;p&gt;Initialement publié &lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/wiki/Petit_precis_de_shell"&gt;ici&lt;/a&gt;. Ce
document est une version améliorée et corrigée.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;&lt;strong&gt;Sommaire&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#quelques-rappels-dunix" id="id1"&gt;Quelques rappels d’Unix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-bases-du-shell" id="id2"&gt;Les bases du shell&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#syntaxe-de-base" id="id3"&gt;Syntaxe de base&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-variables" id="id4"&gt;Les variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#valeurs-de-retour-des-commandes-et-exceptions" id="id5"&gt;Valeurs de retour des commandes et exceptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#executer-une-commande" id="id6"&gt;Exécuter une commande&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conditions-et-iterations" id="id7"&gt;Conditions et itérations&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conditions-if-else" id="id8"&gt;Conditions if … else …&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#la-fonction-test" id="id9"&gt;La fonction test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#tests-sur-les-chaines-de-caracteres" id="id10"&gt;Tests sur les chaînes de caractères&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#tests-sur-les-nombres" id="id11"&gt;Tests sur les nombres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#test-avec-une-commande" id="id12"&gt;Test avec une commande&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#boucles-while-until" id="id13"&gt;Boucles while/until&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#boucle-for" id="id14"&gt;Boucle for&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-tableaux" id="id15"&gt;Les tableaux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#parametres-de-scripts" id="id16"&gt;Paramètres de scripts&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generalites" id="id17"&gt;Généralités&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-parametres-speciaux" id="id18"&gt;Les paramètres spéciaux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-commandes-shift-et-set" id="id19"&gt;Les commandes shift et set&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-fonctions" id="id20"&gt;Les fonctions&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#le-mot-cle-return" id="id21"&gt;Le mot clé return&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-redirections-de-flux" id="id22"&gt;Les redirections de flux&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-flux-sortant" id="id23"&gt;Les flux sortant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#les-flux-entrant" id="id24"&gt;Les flux entrant&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#importer-une-configuration" id="id25"&gt;Importer une configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#mode-debug" id="id26"&gt;Mode debug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#parser-des-arguments" id="id27"&gt;Parser des arguments&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#exemple" id="id28"&gt;Exemple&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#differences-notables-avec-bash" id="id29"&gt;Différences notables avec bash&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#variables-disponibles-uniquement-en-bash" id="id30"&gt;Variables disponibles uniquement en Bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#syntaxe" id="id31"&gt;Syntaxe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#autres" id="id32"&gt;Autres&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#divers" id="id33"&gt;Divers&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#differences-entre-la-sortie-de-ls-et-de-find" id="id34"&gt;Différences entre la sortie de ls et de find&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#et-et-ou-dans-le-langage" id="id35"&gt;ET et OU dans le langage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#sources-et-liens-externes" id="id36"&gt;Sources et liens externes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="quelques-rappels-dunix"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Quelques rappels d’Unix&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Le langage shell est le langage de script qui vient par défaut avec
&lt;em&gt;tous&lt;/em&gt; les Unix. En effet, même si désormais d’autres interpréteurs plus
modernes sont désormais répandus (bash, csh, zsh, etc.), ils ont tous
conservé la compatibilité avec le shell.&lt;/p&gt;
&lt;p&gt;Comme pour la plupart des langages de script, il existe deux façons
d’exécuter des instructions shell :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;directement dans l’interpréteur&lt;/li&gt;
&lt;li&gt;dans un script shell&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour lancer un interpréteur shell, rien de plus simple : lancer un terminal
(graphique ou tty). Et oui, le shell comprend toutes les commandes Unix. Vous
pouvez donc les réutiliser &lt;em&gt;telles quelles&lt;/em&gt; dans vos scripts et utiliser un
simple terminal pour faire des boucles, des conditions et j’en passe. C'est un
des très gros intérêts du langage d'ailleurs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="les-bases-du-shell"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Les bases du shell&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Il est très important de comprendre et de garder à l’esprit qu’en shell
tout est :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;chaîne de caractères (y compris les nombres) ! Entrez &lt;tt class="docutils literal"&gt;echo 1 + 1&lt;/tt&gt;
dans le terminal pour vous en convaincre.&lt;/li&gt;
&lt;li&gt;commande et que donc elles peuvent prendre des arguments (cela
s’éclaircira plus tard)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="syntaxe-de-base"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Syntaxe de base&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Les commandes s’écrivent soit :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;les unes à la suite des autres séparées par ; (peu recommandé)&lt;/li&gt;
&lt;li&gt;séparées les unes des autres par un saut de ligne&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chaque commande peut prendre des options (qui modifient la façon dont la
commande se comporte comme affiche de l’aide, modifier la verbosité de la
sortie, etc.)  de deux types :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;les options courtes (l, r, h pour &lt;tt class="docutils literal"&gt;ls&lt;/tt&gt; par exemple) qui sont passés
comme suit : &lt;tt class="docutils literal"&gt;CMD &lt;span class="pre"&gt;-ARG&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;les options longues (recursive pour &lt;tt class="docutils literal"&gt;rsync&lt;/tt&gt; par exemple) qui se
passent comme ceci : &lt;tt class="docutils literal"&gt;CMD &lt;span class="pre"&gt;--ARGUMENT&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Il est évidement possible de passer plusieurs options à une même
commande.&lt;/p&gt;
&lt;p class="tip"&gt;
Certains paramètres existent sous une forme courte et une forme
longue. Consulter le manuel de la commande pour plus de détails. Le
manuel contient également la liste complète des arguments supportés par
une commande.
&lt;/p&gt;&lt;p class="note"&gt;
Certains commandes ne respectent pas la convention énoncée
ci-dessus. Leurs arguments long se passent avec un seul - (find en est
un exemple).
&lt;/p&gt;&lt;p&gt;Les commandes peuvent aussi prendre des arguments positionnels. Ils se placent
après les paramètres.&lt;/p&gt;
&lt;p&gt;Exemple : &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-R&lt;/span&gt; ~/Documents&lt;/tt&gt;. Par défaut, &lt;tt class="docutils literal"&gt;ls&lt;/tt&gt; ne liste que les
fichiers et dossiers dans le dossier courant. L’option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-R&lt;/span&gt;&lt;/tt&gt; permet de
descendre dans tous les dossiers. L’argument &lt;tt class="docutils literal"&gt;~/Documents&lt;/tt&gt; permet
d’exécuter la commande dans le dossier &lt;tt class="docutils literal"&gt;~/Documents&lt;/tt&gt; sans s’y déplacer.&lt;/p&gt;
&lt;p class="tip"&gt;
Pensez à la commande man qui prend comme argument une autre
commande et affiche son manuel.
&lt;/p&gt;&lt;/div&gt;
&lt;div class="section" id="les-variables"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Les variables&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Les variables se déclarent comme ceci : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;var=&amp;quot;ping&amp;quot;&lt;/span&gt;&lt;/tt&gt;. Notez bien l'absence
d'espaces entre &lt;tt class="docutils literal"&gt;var&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;=&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;&amp;quot;ping&amp;quot;&lt;/tt&gt;. Si vous ajoutez des espaces, le
shell tentera de faire un test. Voir &lt;a class="reference internal" href="#conditions-if-else"&gt;Conditions if … else …&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ensuite, pour utiliser une variable, il faut mettre un &lt;tt class="docutils literal"&gt;$&lt;/tt&gt; devant le nom de la
variable. Par exemple : &lt;tt class="docutils literal"&gt;echo $var&lt;/tt&gt; affichera le contenu de la variable
&lt;tt class="docutils literal"&gt;var&lt;/tt&gt;. La variable est aussi remplacée par sa valeur dans une chaîne si elle
est encadrée par des guillemets mais pas si elle est encadrée par des
apostrophes. Par exemple :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;echo &amp;quot;$var pong&amp;quot;&lt;/tt&gt; affichera &lt;tt class="docutils literal"&gt;ping pong&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;echo '$var pong'&lt;/tt&gt; affichera &lt;tt class="docutils literal"&gt;$var pong&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="valeurs-de-retour-des-commandes-et-exceptions"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Valeurs de retour des commandes et exceptions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Une fois qu’une commande s’est exécutée, elle renvoie une valeur de
retour afin d’informer l’utilisateur. Cette valeur permet en effet de
savoir si la commande s’est exécutée correctement. Voici les valeurs de
retour courantes et leur signification :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;0 : tout va bien&lt;/li&gt;
&lt;li&gt;1 : erreur&lt;/li&gt;
&lt;li&gt;2 : erreur grave&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous pouvez vous aussi utiliser ces valeurs de retour. Par défaut, un
script qui se complète correctement retourne 0. Mais vous pouvez (par
exemple si un utilisateur tente d’exécuter un script qui nécessite un
argument sans) retourner un autre code d’erreur avec la commande
&lt;tt class="docutils literal"&gt;exit&lt;/tt&gt;. Il suffit de lui passer le code qu’elle doit retourner. Votre
script s’arrêtera alors avec le code d’erreur spécifié.&lt;/p&gt;
&lt;p&gt;Vous pouvez connaître la valeur de retour de la dernière commande
exécutée avec la variable &lt;tt class="docutils literal"&gt;$?&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="note"&gt;
Les valeurs de retour ne sont pas limitées à 0, 1, 2. Par convention, c'est
n'importe quel entier positif. À chaque entier est associé une signification,
ce qui permet de comprendre ce qui s'est passé si une commande échoue.
&lt;/p&gt;&lt;/div&gt;
&lt;div class="section" id="executer-une-commande"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Exécuter une commande&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;S’il est facile dans les cas simples d’exécuter une commande, dès lors
qu’en shell tout est chaîne de caractères, si vous voulez affecter la
sortie d’une commande à une variable, vous ne pouvez pas simplement
faire &lt;tt class="docutils literal"&gt;var=CMD&lt;/tt&gt; car var va alors valoir la chaîne CMD.&lt;/p&gt;
&lt;p&gt;Pour obtenir le résultat souhaité vous devez placer CMS entre $(…). Par exemple
: &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;var=$(ls)&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="note"&gt; Vous pouvez aussi mettre la commande entre backquote
`. Mais cette syntaxe ` est plus ancienne et ne doit plus être
utilisée. La syntaxe $(…) présente l’avantage de pouvoir imbriquer les
commandes sans ambiguïté.
&lt;/p&gt;&lt;p&gt;Il est également tout à fait possible de stocker une commande dans une variable
pour l'exécuter ensuite (une fois de plus, tout est chaîne de caractère). Une
commande est en effet une chaîne de caractère située en position 0 sur une
ligne.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;mon_cd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;
&lt;span class="nv"&gt;$mon_cd&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="conditions-et-iterations"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Conditions et itérations&lt;/a&gt;&lt;/h3&gt;
&lt;div class="section" id="conditions-if-else"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id8"&gt;Conditions if … else …&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;La structure générale d’une condition est la suivante :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;if&lt;/span&gt; QQC
&lt;span class="k"&gt;then&lt;/span&gt;
    CMDS
&lt;span class="k"&gt;else&lt;/span&gt;
    CMDS
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Le &lt;tt class="docutils literal"&gt;else&lt;/tt&gt; est facultatif. Il est aussi possible de regrouper &lt;tt class="docutils literal"&gt;if&lt;/tt&gt; et
&lt;tt class="docutils literal"&gt;then&lt;/tt&gt; en une seule ligne comme ceci : &lt;tt class="docutils literal"&gt;if QQC ; then&lt;/tt&gt;. On peut
également utiliser des &lt;tt class="docutils literal"&gt;elif&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;La question que vous devriez avoir est que mettre à la place de &lt;tt class="docutils literal"&gt;QQC&lt;/tt&gt;.
Il y a deux possibilités :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;la fonction &lt;tt class="docutils literal"&gt;test&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;une commande&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="section" id="la-fonction-test"&gt;
&lt;h5&gt;&lt;a class="toc-backref" href="#id9"&gt;La fonction test&lt;/a&gt;&lt;/h5&gt;
&lt;p class="important"&gt;
Dans toute la suite, il faudra faire très &lt;strong&gt;attention aux
espaces&lt;/strong&gt;
&lt;/p&gt;&lt;p&gt;La fonction &lt;tt class="docutils literal"&gt;test&lt;/tt&gt; s’utilise en général comme suit : &lt;tt class="docutils literal"&gt;if [ ARGS ]&lt;/tt&gt; (&lt;strong&gt;Notez
les espaces&lt;/strong&gt;).&lt;/p&gt;
&lt;p class="important"&gt;
La syntaxe &lt;code&gt;if [[ ARGS ]]&lt;/code&gt; n’est valide qu’avec bash.
&lt;/p&gt;&lt;p&gt;Pour faire un test, il suffit ensuite de passer les bons arguments à la
commande. Par exemple, pour tester si une chaîne est vide : &lt;tt class="docutils literal"&gt;if [ &lt;span class="pre"&gt;-z&lt;/span&gt; &amp;quot;$chaine&amp;quot;
]&lt;/tt&gt;. Si l’argument a besoin de deux paramètres pour fonctionner, mettre un
paramètre de chaque côté de celui-ci. Par exemple, pour faire un test d’égalité
de chaîne de caractères : &lt;tt class="docutils literal"&gt;CHAINE1 = CHAINE2&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;On peut aussi combiner les arguments avec des ET et des OU avec les options -a et -o. Le caractère “!” permet de faire une négation.&lt;/p&gt;
&lt;p&gt;On peut également faire des ET avec &lt;tt class="docutils literal"&gt;&amp;amp;&amp;amp;&lt;/tt&gt; et des OU avec &lt;tt class="docutils literal"&gt;||&lt;/tt&gt;. Ces opérateurs
ne sont pas spécifiques à la fonction test, ils font parti du langage. Il est
donc tout à fait possible de les utiliser sans la fonction test.&lt;/p&gt;
&lt;p&gt;Voir ci-dessous pour la liste complète.&lt;/p&gt;
&lt;p&gt;En shell, tout est chaîne de caractère. Bien faire attention au type que l’on
veut tester (chaîne ou nombre).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tests-sur-les-chaines-de-caracteres"&gt;
&lt;h5&gt;&lt;a class="toc-backref" href="#id10"&gt;Tests sur les chaînes de caractères&lt;/a&gt;&lt;/h5&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="39%" /&gt;
&lt;col width="61%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Argument&lt;/th&gt;
&lt;th class="head"&gt;Signification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;=&lt;/td&gt;
&lt;td&gt;égalité&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-z&lt;/td&gt;
&lt;td&gt;chaîne vide&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-n&lt;/td&gt;
&lt;td&gt;chaîne non vide&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p class="important"&gt; Lors des tests de chaîne de caractères,
&lt;strong&gt;entourez la variable de guillemets&lt;/strong&gt;. Sinon, si la chaîne est
vide, le test ne pourra être correctement effectué.  &lt;/p&gt;&lt;/div&gt;
&lt;div class="section" id="tests-sur-les-nombres"&gt;
&lt;h5&gt;&lt;a class="toc-backref" href="#id11"&gt;Tests sur les nombres&lt;/a&gt;&lt;/h5&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="32%" /&gt;
&lt;col width="68%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;Argument&lt;/th&gt;
&lt;th class="head"&gt;Signification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;-eq&lt;/td&gt;
&lt;td&gt;égalité&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-ne&lt;/td&gt;
&lt;td&gt;différent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-lt&lt;/td&gt;
&lt;td&gt;strictement plus petit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-gt&lt;/td&gt;
&lt;td&gt;strictement plus grand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-ge&lt;/td&gt;
&lt;td&gt;plus grand ou égal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;-le&lt;/td&gt;
&lt;td&gt;plus petit ou égal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="section" id="test-avec-une-commande"&gt;
&lt;h5&gt;&lt;a class="toc-backref" href="#id12"&gt;Test avec une commande&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Comme indiqué précédemment, une commande qui s’exécute correctement est
considérée comme vraie. Ainsi, il est tout a fait possible, par exemple,
pour savoir si on arrive à se connecter à un serveur mysql de faire
simplement : &lt;tt class="docutils literal"&gt;if mysql &lt;span class="pre"&gt;-h&lt;/span&gt; HOST &lt;span class="pre"&gt;-u&lt;/span&gt; asso &lt;span class="pre"&gt;-pTATA&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;p class="tip"&gt;
Parfois vous pourrez rencontrer des problèmes. Pensez alors
à donner cette commande en argument à la fonction test.
&lt;/p&gt;

&lt;p class="tip"&gt;
Le shell contient deux fonctions utiles: &lt;em&gt;true&lt;/em&gt; et &lt;em&gt;false&lt;/em&gt;. La
première renvoie toujours 0 et la seconde toujours 1. Vous pouvez les
trouver utiles si vous avez besoin de manipuler des booléens.
&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="boucles-while-until"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id13"&gt;Boucles while/until&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;La structure générale est la suivante :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;while&lt;/span&gt; QQC
&lt;span class="k"&gt;do&lt;/span&gt;
    CMD
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il est possible de regrouper &lt;tt class="docutils literal"&gt;while QQC&lt;/tt&gt; et le &lt;tt class="docutils literal"&gt;do&lt;/tt&gt; en
&lt;tt class="docutils literal"&gt;while QQC ; do&lt;/tt&gt;. Le QQC peut être remplacer par exactement les mêmes
choses que pour la condition. Se référer à cette section pour les
précisions.&lt;/p&gt;
&lt;p&gt;Le shell propose également le mot clé &lt;tt class="docutils literal"&gt;until QQC&lt;/tt&gt; qui fait une action
jusqu’à ce que QQC soit réalisé (équivalent de &lt;tt class="docutils literal"&gt;while ! QQC&lt;/tt&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="boucle-for"&gt;
&lt;h4&gt;&lt;a class="toc-backref" href="#id14"&gt;Boucle for&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;L’utilisation de la boucle for en shell ressemble à celle de python. La
structure générale est la suivante :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; var in &lt;span class="sb"&gt;`&lt;/span&gt;CMD&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;do&lt;/span&gt;
   CMD
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;La variable &lt;em&gt;var&lt;/em&gt; va alors prendre une à une les valeurs données par
CMD. Par exemple, &lt;tt class="docutils literal"&gt;for file in $(ls)&lt;/tt&gt; la variable var va prendre tour à
tour le nom de tous les fichiers et dossiers donnés par la commande
&lt;tt class="docutils literal"&gt;ls&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Vous pouvez également utiliser for pour boucler d’un nombre à un autre
avec la syntaxe : &lt;tt class="docutils literal"&gt;for i in $(seq [first [incr]] last)&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="les-tableaux"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id15"&gt;Les tableaux&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Un tableau se crée comme ceci : &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tab=(un&lt;/span&gt; deux trois)&lt;/tt&gt;. On accède à un élément
grâce à son index (les index commencent à zéros) :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;un deux trois&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[42]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Ne renvoie rien, index en dehors de la plage défini.&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Idem pour l'assignation :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
tab&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;zero
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Renvoie zero.&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Les index ne sont pas obligatoirement continus :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
tab&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="o"&gt;]=&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[42]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Renvoie 42.
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[9]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# Ne renvoie rien.&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut facilement connaître le nombre d'élément du tableau avec
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${#tab[&amp;#64;]}&lt;/span&gt;&lt;/tt&gt;. Il est également facile de parcourir tous les éléments :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;for&lt;/span&gt; elt in &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;[&amp;#64;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$elt&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Va afficher :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
12
deux
trois
42
&lt;/pre&gt;
&lt;p&gt;On peut également afficher tout le tableau avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;${tab[&amp;#64;]}&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="parametres-de-scripts"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id16"&gt;Paramètres de scripts&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="generalites"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id17"&gt;Généralités&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Un script peut prendre des paramètres qui ont le même but que les
arguments d’une fonction : lui passer des informations. Un paramètre
peut être :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;une variable&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;une chaîne de caractère (donc un nombre, en shell on ne fait pas la
distinction). Si la chaîne à passer en paramètre contient plusieurs
mots séparés par des espaces, ne pas oublier de la mettre entre ‘ ou
“.&lt;/p&gt;
&lt;p class="tip"&gt;
Si une variable coucou contient la chaîne ‘salut’, alors
‘$coucou toi’ sera compris &lt;em&gt;$coucou toi&lt;/em&gt; tandis que &lt;em&gt;$coucou toi&lt;/em&gt; sera
interprétée en &lt;em&gt;salut toi&lt;/em&gt;
&lt;/p&gt;&lt;p&gt;Les paramètres se passent à un script comme ceux d’une commande. Ils
sont ensuite disponibles dans l’ordre avec des numéros :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;le premier : $1&lt;/li&gt;
&lt;li&gt;le deuxième : $2&lt;/li&gt;
&lt;li&gt;et ainsi de suite&lt;/li&gt;
&lt;/ul&gt;
&lt;p class="important"&gt;
Le shell ne supporte &lt;strong&gt;que&lt;/strong&gt; 9 paramètres.
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="les-parametres-speciaux"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id18"&gt;Les paramètres spéciaux&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$0&lt;/tt&gt; : contient le nom du script&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$#&lt;/tt&gt; : contient le nombre d’arguments passés au script&lt;/p&gt;
&lt;p class="important"&gt;
Le paramètre &lt;code&gt;$0&lt;/code&gt; est toujours passé au script. &lt;code&gt;$#&lt;/code&gt; est donc
toujours supérieur ou égal à 1.
&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$?&lt;/tt&gt; : le code de retour de la dernière commande invoquée&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$$&lt;/tt&gt; : le PID du shell qui exécute le script&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$!&lt;/tt&gt; : le PID du dernier processus lancé en arrière plan&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$*&lt;/tt&gt; : l’ensemble des paramètres en un seul argument&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;tt class="docutils literal"&gt;$&amp;#64;&lt;/tt&gt; : L’ensemble des arguments, un argument par paramètre&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour bien voir la différence entre &lt;tt class="docutils literal"&gt;$*&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;$&amp;#64;&lt;/tt&gt;, il suffit de regarder la
sortie du script suivant :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Avec $*'&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; param in &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Avec $&amp;#64;'&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; param in &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$&amp;#64;&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="les-commandes-shift-et-set"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id19"&gt;Les commandes shift et set&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;La commande &lt;tt class="docutils literal"&gt;set&lt;/tt&gt; permet d’affecter les paramètres. Ainsi &lt;tt class="docutils literal"&gt;set bonjour salut
bonsoir&lt;/tt&gt; va initialiser &lt;tt class="docutils literal"&gt;$1&lt;/tt&gt; à bonjour, &lt;tt class="docutils literal"&gt;$2&lt;/tt&gt; à salut et &lt;tt class="docutils literal"&gt;$3&lt;/tt&gt; à
bonsoir. Les paramètres spéciaux &lt;tt class="docutils literal"&gt;$#&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;$*&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;$&amp;#64;&lt;/tt&gt; sont mis à jour.&lt;/p&gt;
&lt;p&gt;La commande &lt;tt class="docutils literal"&gt;shift&lt;/tt&gt; permet de décaler les variables. Ainsi, si après &lt;tt class="docutils literal"&gt;shift&lt;/tt&gt;
&lt;tt class="docutils literal"&gt;$1&lt;/tt&gt; prend la valeur de &lt;tt class="docutils literal"&gt;$2&lt;/tt&gt; et ainsi de suite.  &lt;tt class="docutils literal"&gt;shift n&lt;/tt&gt; décale les
arguments de n.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="les-fonctions"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id20"&gt;Les fonctions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Il est tout à fait possible de définir en shell des fonctions que ce
soit dans un script ou un terminal. La syntaxe est la même.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
nom_de_la_fonction &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
 CMDS
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;ou encore&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;function&lt;/span&gt; nom_de_la_fonction &lt;span class="o"&gt;{&lt;/span&gt;
 CMDS
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Les fonctions ainsi créées s’utilisent comme les commandes classiques et leurs
arguments se manipulent exactement comme ceux d’un script. Voir la section
dédiée. Il faut néanmoins faire attention à deux points :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;la portée des variables&lt;/li&gt;
&lt;li&gt;la valeur de retour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Par défaut, les variables définies dans la fonction resteront accessibles une
fois la fonction exécutée. De même les variables définies auparavant restent
accessibles dans la fonction. &lt;strong&gt;Ces variables sont donc globales par défaut.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pour qu’une variable soit locale, il faut utiliser le mot clé &lt;tt class="docutils literal"&gt;local&lt;/tt&gt; lors de
sa définition.  Par exemple : &lt;tt class="docutils literal"&gt;local nom=clubdrupal&lt;/tt&gt; (NB : &lt;tt class="docutils literal"&gt;local&lt;/tt&gt; est une
commande qui peut prendre des options).&lt;/p&gt;
&lt;p&gt;Pour qu’une fonction en bash retourne une valeur comme vous pouvez en avoir
l’habitude dans d’autres langages, il faut utiliser la commande &lt;cite&gt;echo`&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;Il faut alors faire très attention car si la sortie n'est pas capturée dans une
variable, elle s'affiche dans le terminal. Par exemple avec la fonction suivante :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
x_files &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;top_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/urandom &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt; /dev/null &lt;span class="p"&gt;|&lt;/span&gt; cksum &lt;span class="p"&gt;|&lt;/span&gt; cut -f1 -d&lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$top_secret&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="section" id="le-mot-cle-return"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id21"&gt;Le mot clé return&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Comme la plupart des langages, le shell dispose d'un mot clé &lt;tt class="docutils literal"&gt;return&lt;/tt&gt;. Lorsque
ce mot clé est exécuté dans une fonction, cette fonction est exécuté jusqu'à ce
mot clé, puis l'exécution du programme reprend à l'instruction suivante. Ce mot
clé est particulièrement utile pour que des fonctions renvoient des codes
d'erreur sans pour autant arrêter le script (ce que &lt;tt class="docutils literal"&gt;exit&lt;/tt&gt; aurait fait).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="les-redirections-de-flux"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id22"&gt;Les redirections de flux&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="les-flux-sortant"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id23"&gt;Les flux sortant&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Les flux représentent les sorties générées par les commandes. Par défaut, il
existe deux flux :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;le flux standard&lt;/li&gt;
&lt;li&gt;le flux d’erreur&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Par défaut, il s’affiche sur la sortie standard (votre écran pour être bref). Il
peut s’avérer intéressant d’envoyer ces flux ailleurs (logs, le néant,
etc.). Pour cela, on va les rediriger. Par exemple pour rediriger la sortie de
&lt;tt class="docutils literal"&gt;ls&lt;/tt&gt; dans un fichier nommé toto, on fait :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;ls &amp;gt; toto&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ou&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;ls &amp;gt;&amp;gt; toto&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La première solution efface le contenu du fichier puis écrit dedans.  La seconde
ajoute la sortie à la fin du fichier. On a ici redirigé le flux standard. Pour
rediriger les flux d’erreurs, on utilise les symboles &lt;tt class="docutils literal"&gt;2&amp;gt;&lt;/tt&gt; ou &lt;tt class="docutils literal"&gt;2&amp;gt;&amp;gt;&lt;/tt&gt;. On peut
évidemment combiner les deux : &lt;tt class="docutils literal"&gt;ls &lt;span class="pre"&gt;-R&lt;/span&gt; / &amp;gt; mes_fichiers.txt 2&amp;gt; errors.log&lt;/tt&gt; avec
toutes les variantes possibles.&lt;/p&gt;
&lt;p&gt;Pour rediriger l’erreur au même endroit que l’entrée, on peut faire &lt;tt class="docutils literal"&gt;ls &amp;gt; toto
2&amp;gt; toto&lt;/tt&gt; ou plus simplement &lt;tt class="docutils literal"&gt;ls &amp;gt; toto &lt;span class="pre"&gt;2&amp;gt;&amp;amp;1&lt;/span&gt;&lt;/tt&gt;.  Pour rediriger une sortie vers
le néant, on l’envoie dans &lt;tt class="docutils literal"&gt;/dev/null&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="les-flux-entrant"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id24"&gt;Les flux entrant&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Il est également possible de passer en paramètre le contenu d’un fichier. Pour
cela, on utilise le symbole &amp;lt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="importer-une-configuration"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id25"&gt;Importer une configuration&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Il est tout à fait possible d’écrire un fichier de configuration contenant les
variables et les fonctions indispensables à d’autres scripts et les réutiliser
facilement dans ceux-ci. Pour cela, respecter la syntaxe shell dans le fichier
puis au début du script qui en a besoin, placer la ligne : &lt;tt class="docutils literal"&gt;. &lt;span class="pre"&gt;config-file.sh&lt;/span&gt;&lt;/tt&gt;
pour l’importer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="mode-debug"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id26"&gt;Mode debug&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Lorsqu’un de vos scripts shell bug il peut être difficile de savoir d’où vient
le problème. Heureusement, le shell propose un mode débug qui vous dit pour
chaque ligne comment elle est exécuté, avec quels paramètres (les variables sont
remplacées par leur contenu).  Il suffit de faire : &lt;tt class="docutils literal"&gt;sh &lt;span class="pre"&gt;-x&lt;/span&gt; SCRIPT&lt;/tt&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="parser-des-arguments"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id27"&gt;Parser des arguments&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Il existe deux commandes pour parser des arguments en shell : &lt;tt class="docutils literal"&gt;getopts&lt;/tt&gt;, qui
est une commande ”builtin&amp;quot; qui ne supporte que les options courtes et
&lt;tt class="docutils literal"&gt;getopt&lt;/tt&gt;, qui est une commande à part, pas forcément présente mais qui
supporte les arguments courts et longs.  Nous n’étudierons ici que getopts qui a
l’avantage d’être présent partout.&lt;/p&gt;
&lt;p&gt;La commande s’utilise comme suit :&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
while getopts &amp;quot;options&amp;quot; opt; do
  case &amp;quot;$opt&amp;quot; in
    option1) action;;
  esac
done
&lt;/pre&gt;
&lt;p&gt;Ainsi, pour utiliser l’option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-o&lt;/span&gt;&lt;/tt&gt; :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;o&amp;quot;&lt;/span&gt; opt&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
    o&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;tt class="docutils literal"&gt;script &lt;span class="pre"&gt;-o&lt;/span&gt;&lt;/tt&gt; affera : &lt;tt class="docutils literal"&gt;o&lt;/tt&gt;. Si on le lance avec l’option -a, il
affichera :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
illegal option -- a
&lt;/pre&gt;
&lt;p class="tip"&gt; Il est possible d’utiliser getopts en mode erreurs
silencieuses en ajoutant : au début de la chaîne des options.  &lt;/p&gt;&lt;p&gt;Si votre option a besoin d’un argument, il suffit de placer : après son
nom :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;ob:&amp;quot;&lt;/span&gt; opt&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
    o&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
    b&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt; used with option &lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Une fois vos arguments parser, vous pouvez mettre le premier argument
positionel de votre script dans &lt;tt class="docutils literal"&gt;$1&lt;/tt&gt; avec :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="k"&gt;$((&lt;/span&gt;OPTIND-1&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Vous pouvez aussi utiliser dans le &lt;tt class="docutils literal"&gt;case&lt;/tt&gt; &lt;em&gt;?&lt;/em&gt; pour afficher un message si
l’utilisateur passe une option inconnue et &lt;em&gt;:&lt;/em&gt; pour afficher un message si une
option qui requiert un argument ne l’a pas eu.&lt;/p&gt;
&lt;div class="section" id="exemple"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id28"&gt;Exemple&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;:h:u:p:P&amp;quot;&lt;/span&gt; opt
&lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
        h&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;hflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        u&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;uflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        p&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;passwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;pflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        P&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;Pflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        :&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Option -&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="s2"&gt; requires an argument.&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
            usage&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
        &lt;span class="se"&gt;\?&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            usage&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="k"&gt;$((&lt;/span&gt;OPTIND-1&lt;span class="k"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# To get the 1st positional argument with $1&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="differences-notables-avec-bash"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id29"&gt;Différences notables avec bash&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="variables-disponibles-uniquement-en-bash"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id30"&gt;Variables disponibles uniquement en Bash&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;RANDOM (pour la génération de nombre aléatoire). Voir les &lt;a class="reference external" href="/posts/2014/Sep/07/diverses-astuces-shell/"&gt;trucs et astuces&lt;/a&gt; pour plus de détails.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="syntaxe"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id31"&gt;Syntaxe&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&amp;amp;&amp;gt;&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;|&amp;amp;&lt;/tt&gt;. Permettent de rediriger tous les flux vers un fichier ou
de passer tous les flux à une commande (pipe généralisé)&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;{2..10}&lt;/span&gt;&lt;/tt&gt; pour générer des séquences de nombres&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;[[ ARGS ]]&lt;/tt&gt; : permet de faire des tests de façon plus facile ou
agréable. Exemple : &lt;tt class="docutils literal"&gt;[[ chaine == chaine2 ]]&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;=~&lt;/tt&gt; : s'utilise conjointement avec &lt;tt class="docutils literal"&gt;[[ ]]&lt;/tt&gt; pour tester si la chaîne
de gauche est contenu dans celle de droite&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;$((ARGS))&lt;/span&gt;&lt;/tt&gt; est un raccourcis pour la fonction let&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="autres"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id32"&gt;Autres&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Le nombre de paramètres en bash n’est pas limité à 9. Les paramètres
positionnels de numéros supérieurs à 10 s’appellent comme suit :
&lt;tt class="docutils literal"&gt;${num}&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="divers"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id33"&gt;Divers&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="differences-entre-la-sortie-de-ls-et-de-find"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id34"&gt;Différences entre la sortie de ls et de find&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;ls&lt;/tt&gt; renvoie simplement la liste des fichiers.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;find&lt;/tt&gt; renvoie un chemin absolu si l’argument donnée est un chemin
absolu et relatif (de la forme ./fichier) si l’argument est .&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="et-et-ou-dans-le-langage"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id35"&gt;ET et OU dans le langage&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;L’opérateur &lt;tt class="docutils literal"&gt;&amp;amp;&amp;amp;&lt;/tt&gt; permet de réaliser un ET paresseux entre deux commandes.
Ainsi, par exemple : &lt;tt class="docutils literal"&gt;cmd1 &amp;amp;&amp;amp; cmd2&lt;/tt&gt;. &lt;tt class="docutils literal"&gt;cmd2&lt;/tt&gt; ne sera exécuté que si
&lt;tt class="docutils literal"&gt;cmd1&lt;/tt&gt; a pu s’exécuter correctement. En outre le code de retour de
l’ensemble ne sera 0 que si les deux commandes ont pu s’exécuter
correctement.&lt;/p&gt;
&lt;p&gt;L’opérateur &lt;tt class="docutils literal"&gt;||&lt;/tt&gt; permet de réaliser un OU paresseux entre deux
commandes. Ainsi, par exemple : &lt;tt class="docutils literal"&gt;cmd1 || cmd2&lt;/tt&gt;. Si &lt;tt class="docutils literal"&gt;cmd1&lt;/tt&gt; s’exécute
correctement &lt;tt class="docutils literal"&gt;cmd2&lt;/tt&gt; ne sera pas exécutée. Si &lt;tt class="docutils literal"&gt;cmd1&lt;/tt&gt; retourne une
erreur, &lt;tt class="docutils literal"&gt;cmd2&lt;/tt&gt; sera exécutée. Le code de retour de l’ensemble
correspond à un OU entre les deux codes de retour.&lt;/p&gt;
&lt;p&gt;Ceci peut s’utiliser dans les conditions.&lt;/p&gt;
&lt;p&gt;Des fonctionnalités analogues existes dans d’autres langages inspirés du
shell comme Perl ou PHP.&lt;/p&gt;
&lt;p&gt;Pour exécuter simplement deux commandes à la suite des autres sur une
seule ligne, il suffit de séparer les commandes par un point virgule.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="sources-et-liens-externes"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id36"&gt;Sources et liens externes&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Quelques règles de style. &lt;strong&gt;Certains points ne s’appliquent qu’à
bash&lt;/strong&gt; : &lt;a class="reference external" href="http://google-styleguide.googlecode.com/svn/trunk/shell.xml"&gt;http://google-styleguide.googlecode.com/svn/trunk/shell.xml&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.siteduzero.com/informatique/tutoriels/reprenez-le-controle-a-l-aide-de-linux"&gt;http://www.siteduzero.com/informatique/tutoriels/reprenez-le-controle-a-l-aide-de-linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.commentcamarche.net/faq/5444-bash-les-parametres"&gt;http://www.commentcamarche.net/faq/5444-bash-les-parametres&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Programmation"></category><category term="Linux"></category><category term="Unix"></category><category term="Bash/Shell"></category></entry><entry><title>Zsh, c'est trop cool</title><link href="//www.jujens.eu/posts/2014/Sep/06/oh-my-zsh/" rel="alternate"></link><published>2014-09-06T00:00:00+02:00</published><updated>2014-09-06T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-09-06:/posts/2014/Sep/06/oh-my-zsh/</id><summary type="html">&lt;p&gt;Depuis plusieurs mois maintenant, j'utilise zsh comme interpréteur par
défaut. L'un des principaux avantages de zsh par rapport à bash est la
possibilité de complétion avancée. Sous bash, lorsqu'on appuie sur &amp;lt;TAB&amp;gt; pour
obtenir la complétion d'une commande, bash se contente de lister les
possibilités. Sous zsh, les pressions suivantes …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Depuis plusieurs mois maintenant, j'utilise zsh comme interpréteur par
défaut. L'un des principaux avantages de zsh par rapport à bash est la
possibilité de complétion avancée. Sous bash, lorsqu'on appuie sur &amp;lt;TAB&amp;gt; pour
obtenir la complétion d'une commande, bash se contente de lister les
possibilités. Sous zsh, les pressions suivantes sur &amp;lt;TAB&amp;gt; passe en revue les
autres. Cela fonctionne également pour les arguments des commandes.&lt;/p&gt;
&lt;p&gt;Mais ce n'est pas tout. Avec bash, le raccourcis &lt;tt class="docutils literal"&gt;^w&lt;/tt&gt; supprime l'intégralité
de la chaîne juste à gauche du curseur. Si la chaîne est un chemin, zsh va
simplement supprimer les caractères jusqu'au '/' le plus proche.&lt;/p&gt;
&lt;p&gt;Zsh est aussi capable de proposer des corrections de commande. Ainsi, si je tape
&lt;tt class="docutils literal"&gt;systemctlw&lt;/tt&gt; au lieu de &lt;tt class="docutils literal"&gt;systemd&lt;/tt&gt; et que cette commande n'existe pas, zsh va
me proposer la correction :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
zsh: correct 'systemctlw' to 'systemctl' [nyae]?
&lt;/pre&gt;
&lt;p&gt;Autre point très intéressant pour un développeur, si le dossier courant est géré
par git, zsh est capable d'afficher diverses informations telles que la branche,
s'il y a des fichiers modifiés mais non commités ou encore le nombre de jours
depuis le dernier commit. Cette fonctionnalité est aussi disponible pour
mercurial mais dans une moindre mesure.&lt;/p&gt;
&lt;p&gt;J'espère vous avoir convaincu que la puissance de zsh. Si vous avez très
certainement déjà un paquet zsh dans les dépôts de votre distribution, je vous
conseille d'utiliser le projet &lt;a class="reference external" href="http://ohmyz.sh/"&gt;Oh my zsh!&lt;/a&gt;. Le but de ce
projet est de fournir un framework de configuration pour zsh. Il contient de
&lt;a class="reference external" href="https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins"&gt;nombreux plugins&lt;/a&gt;
(plus de 150 d'après le site officiel) et de &lt;a class="reference external" href="https://github.com/robbyrussell/oh-my-zsh/wiki/Themes"&gt;nombreux thèmes&lt;/a&gt; (plus de 100 d'après
le site).&lt;/p&gt;
&lt;p&gt;La plupart des options courantes (comme l'activation de l'autocorrection) sont
activables via des variables dans le fichier .zshrc. Le système de plugins va
vous permettre de facilement utiliser de nouveaux alias (gp pour &lt;tt class="docutils literal"&gt;git push&lt;/tt&gt;,
gup pour &lt;tt class="docutils literal"&gt;git pull &lt;span class="pre"&gt;--rebase&lt;/span&gt;&lt;/tt&gt;), les informations fournies par git, la
possibilité d'ajouter &lt;tt class="docutils literal"&gt;sudo&lt;/tt&gt; devant une commande en pressant deux fois ESC, de
faire automatiquement appel à sudo pour les commandes systemd qui en ont besoin
et bien plus !&lt;/p&gt;
&lt;p&gt;Pour finir, voilà une petite capture de mon terminal. Il affiche des
informations sur l'état d'un dépôt git, un cercle rouge si une commande à un
code de retour différent de 0. Il s'agit du thème avit légèrement modifié.&lt;/p&gt;
&lt;img alt="Une capture de mon terminal avec un thème oh-my-zsh" src="/images/zsh.png" /&gt;
</content><category term="Trucs et astuces"></category><category term="Zsh"></category><category term="Bash/Shell"></category><category term="Linux"></category></entry><entry><title>Réaliser des diagramme FAST en LaTeX</title><link href="//www.jujens.eu/posts/2014/Aug/13/diagramme-fast-latex/" rel="alternate"></link><published>2014-08-13T00:00:00+02:00</published><updated>2014-08-13T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-08-13:/posts/2014/Aug/13/diagramme-fast-latex/</id><summary type="html">&lt;p&gt;J'ai récemment eu besoin d'insérer des diagrammes FAST dans un rapport en
LaTeX. J'ai d'abord pensé les réaliser sur un logiciel de diagramme comme &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Dia_%28software%29"&gt;dia&lt;/a&gt; pour l'insérer comme une
image et puis j'ai découvert le paquet &lt;a class="reference external" href="http://www.tug.org/texlive//devsrc/Master/texmf-dist/doc/latex/fast-diagram/help.pdf"&gt;fast-diagram&lt;/a&gt;
qui définit un environnent et des commandes LaTeX pour réaliser un joli
diagramme …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai récemment eu besoin d'insérer des diagrammes FAST dans un rapport en
LaTeX. J'ai d'abord pensé les réaliser sur un logiciel de diagramme comme &lt;a class="reference external" href="http://en.wikipedia.org/wiki/Dia_%28software%29"&gt;dia&lt;/a&gt; pour l'insérer comme une
image et puis j'ai découvert le paquet &lt;a class="reference external" href="http://www.tug.org/texlive//devsrc/Master/texmf-dist/doc/latex/fast-diagram/help.pdf"&gt;fast-diagram&lt;/a&gt;
qui définit un environnent et des commandes LaTeX pour réaliser un joli
diagramme FAST facilement.&lt;/p&gt;
&lt;p&gt;C'est très simple d'utilisation, on importe le paquet avec
&lt;code class="highlight latex"&gt;&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[raccourcis]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fast-digram&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; et ensuite :&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fast&lt;span class="nb"&gt;}{&lt;/span&gt;Fonction de service&lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="k"&gt;\FT&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;FT1&lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="nb"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;\FT&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;FT2&lt;span class="nb"&gt;}&lt;/span&gt;
         &lt;span class="nb"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;\ST&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Solution technique&lt;span class="nb"&gt;}&lt;/span&gt;
         &lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="k"&gt;\FT&lt;/span&gt;&lt;span class="nb"&gt;{}&lt;/span&gt;
       &lt;span class="nb"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;\FT&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;FT3&lt;span class="nb"&gt;}&lt;/span&gt;
         &lt;span class="nb"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;\ST&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;ST2&lt;span class="nb"&gt;}&lt;/span&gt;
         &lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="k"&gt;\FT&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;FT4&lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="nb"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;\ST&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;ST3&lt;span class="nb"&gt;}&lt;/span&gt;
       &lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fast&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\fastReset&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;ce qui donne :&lt;/p&gt;
&lt;img alt="Un diagramme fast réalisé en LaTeX" src="/images/diagramme-fast-LaTeX.png" style="width: 150%;" /&gt;
&lt;p&gt;On peut également modifier la largeur des boîtes avec
&lt;code class="highlight latex"&gt;&lt;span class="k"&gt;\renewcommand*&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\fastLargeurBoite&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;8em&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt; par exemple pour une largeur de
8em. Idem pour la hauteur avec &lt;code class="highlight latex"&gt;&lt;span class="k"&gt;\renewcommand*&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\fastHauteurBoite&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;3em&lt;span class="nb"&gt;}&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;C'est facile et très complet. La documentation complète est là :
&lt;a class="reference external" href="http://www.tug.org/texlive//devsrc/Master/texmf-dist/doc/latex/fast-diagram/help.pdf"&gt;http://www.tug.org/texlive//devsrc/Master/texmf-dist/doc/latex/fast-diagram/help.pdf&lt;/a&gt;&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="LaTeX"></category><category term="diagramme FAST"></category></entry><entry><title>Rédiger ses rapports avec rst et sphinx</title><link href="//www.jujens.eu/posts/2014/Aug/13/rapport-rst-sphinx/" rel="alternate"></link><published>2014-08-13T00:00:00+02:00</published><updated>2014-08-13T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-08-13:/posts/2014/Aug/13/rapport-rst-sphinx/</id><summary type="html">&lt;p&gt;Comme je l'ai déjà évoqué &lt;a class="reference external" href="/posts/2013/Aug/23/de-latex-a-orgmode/"&gt;ici&lt;/a&gt; et &lt;a class="reference external" href="/posts/2014/May/10/langages-balisage/"&gt;là&lt;/a&gt;, j'adore les langages à balisage
léger. Du coup, j'essaie de les utiliser partout où je peux. Mais de là à
rédiger un rapport avec table des matières, pages de garde et glossaire, il y a
un pas. Surtout face à la puissance …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Comme je l'ai déjà évoqué &lt;a class="reference external" href="/posts/2013/Aug/23/de-latex-a-orgmode/"&gt;ici&lt;/a&gt; et &lt;a class="reference external" href="/posts/2014/May/10/langages-balisage/"&gt;là&lt;/a&gt;, j'adore les langages à balisage
léger. Du coup, j'essaie de les utiliser partout où je peux. Mais de là à
rédiger un rapport avec table des matières, pages de garde et glossaire, il y a
un pas. Surtout face à la puissance de LaTeX.&lt;/p&gt;
&lt;p&gt;J'avais déjà évoqué org-mode &lt;a class="reference external" href="/posts/2013/Aug/23/de-latex-a-orgmode/"&gt;ici&lt;/a&gt; et
pourquoi j'envisageais de l'utiliser en lieu et place de LaTeX, à savoir :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Bonne intégration avec Emacs&lt;/li&gt;
&lt;li&gt;Syntaxe légère&lt;/li&gt;
&lt;li&gt;Possibilité d'export en LaTeX&lt;/li&gt;
&lt;li&gt;Possibilité d'insérer du code LaTeX&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mais comme je n'ai pas trouvé de bon support pour org-mode dans Pelican, je m'en
suis un peu détourné (je l'utilise toujours pour mes notes) au profit le
Restructured Text. Comme ce langage a été conçu pour remplacer LaTeX lors pour
la génération HTML de la documentation de python, il est particulièrement
puissant. J'ai donc décidé de l'utiliser pour rédiger mon rapport de stage.&lt;/p&gt;
&lt;p&gt;Je vais vous présenter tout d'abord Restructured Text (rst) puis sphinx (qui est
utilisé pour générer la documentation à partir de fichiers rst) et pourquoi je
conseille son utilisation pour un rapport plutôt que juste rst.&lt;/p&gt;
&lt;div class="section" id="restructured-text"&gt;
&lt;h2&gt;Restructured Text&lt;/h2&gt;
&lt;div class="section" id="presentation"&gt;
&lt;h3&gt;Présentation&lt;/h3&gt;
&lt;p&gt;La syntaxe est simple. Un bloc de texte constitue un paragraphe. On sépare les
paragraphes avec un saut de ligne. On peut écrire en &lt;em&gt;italique&lt;/em&gt; et en &lt;strong&gt;gras&lt;/strong&gt; :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="ge"&gt;*italique*&lt;/span&gt; et en &lt;span class="gs"&gt;**gras**&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On peut faire des listes numérotées ou non (attention, les tirets et les dièses
doivent être correctement aligné et les sous listes doivent être séparées de la
liste par un saut de ligne) :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="m"&gt;-&lt;/span&gt; item 1
&lt;span class="m"&gt;-&lt;/span&gt; item 2

  &lt;span class="m"&gt;#.&lt;/span&gt; Sous-liste numérotée
  &lt;span class="m"&gt;#.&lt;/span&gt; Un deuxième élément de la sous-liste numérotée
&lt;/pre&gt;
&lt;p&gt;On peut inclure des images :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;image&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; /images/diagramme-fast-LaTeX.png
           &lt;span class="nc"&gt;:alt:&lt;/span&gt; Un diagramme fast réalisé en LaTeX
           &lt;span class="nc"&gt;:width:&lt;/span&gt; 150%
&lt;/pre&gt;
&lt;p&gt;du code :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;code&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; python

          print('Hello World')
&lt;/pre&gt;
&lt;p&gt;Il est tout à fait possible de découper son fichier en plusieurs fichiers plus
petits, puis de les inclure avec :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;include&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; fichier.rst
&lt;/pre&gt;
&lt;p&gt;On peut également insérer des fichiers LaTeX avec la directive :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; latex
         &lt;span class="nc"&gt;:file:&lt;/span&gt; fast.tex
&lt;/pre&gt;
&lt;p&gt;La syntaxe complète est disponible &lt;a class="reference external" href="http://docutils.sourceforge.net/docs/user/rst/quickstart.html"&gt;en ligne&lt;/a&gt;. Elle peut
paraître déroutante au début, mais on s'y fait et dans l'ensemble, je la trouve
très bien faite (de même que la documentation d'ailleurs).&lt;/p&gt;
&lt;p&gt;On peut ensuite exporter son fichier en HTML ou LaTeX avec respectivement
&lt;tt class="docutils literal"&gt;rst2html&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;rst2latex&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="rediger-son-rapport"&gt;
&lt;h3&gt;Rédiger son rapport&lt;/h3&gt;
&lt;p&gt;Rien de bien fantastique, on entre son texte en respectant la syntaxe, on insère
la table des matière avec &lt;tt class="docutils literal"&gt;.. contents::&lt;/tt&gt; et on exporte le tout avec
&lt;tt class="docutils literal"&gt;rst2latex&lt;/tt&gt;. On compile ensuite ce fichier avec &lt;tt class="docutils literal"&gt;latexmk&lt;/tt&gt;. On obtient un
fichier Pdf tout ce qu'il y a de plus joli (normal me direz-vous, c'est LaTeX
qui l'a fait).&lt;/p&gt;
&lt;p&gt;Mais cela ne résout pas tout, comme :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Comment fait-on une page de garde ?&lt;/li&gt;
&lt;li&gt;Comment utilise-t-on une autre police ?&lt;/li&gt;
&lt;li&gt;Comment insère-t-on un glossaire ?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;La réponse aux deux premières questions tient en un mot : template ! En effet,
&lt;tt class="docutils literal"&gt;rst2latex&lt;/tt&gt; dispose d'un argument &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--template&lt;/span&gt;&lt;/tt&gt; au quel on peut passer un
fichier contenant du code LaTeX et des variables rst pour personnaliser le
fichier pdf.&lt;/p&gt;
&lt;p&gt;Le fichier template de base s'appelle default.tex et se trouve ici :
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/usr/lib/python3.3/site-packages/docutils/writers/latex2e/default.tex&lt;/span&gt;&lt;/tt&gt; (sur
mon PC du moins). Il est assez basique :&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;head_prefix&lt;/span&gt;&lt;span class="c"&gt;% generated by Docutils &amp;lt;http://docutils.sourceforge.net/&amp;gt;
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{fixltx&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;e} &lt;/span&gt;&lt;span class="c"&gt;% LaTeX patches, \textsubscript
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{cmap} &lt;/span&gt;&lt;span class="c"&gt;% fix search and cut-and-paste in Acrobat
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;requirements
&lt;span class="c"&gt;%%% Custom LaTeX preamble
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;latex_preamble
&lt;/span&gt;&lt;span class="c"&gt;%%% User specified packages and stylesheets
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;stylesheet
&lt;span class="c"&gt;%%% Fallback definitions for Docutils-specific commands
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;fallbacks&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;pdfsetup
&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;titledata
&lt;/span&gt;&lt;span class="c"&gt;%%% Body
&lt;/span&gt;&lt;span class="nv"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{document}
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;body&lt;span class="nb"&gt;_&lt;/span&gt;pre&lt;span class="nb"&gt;_&lt;/span&gt;docinfo&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;docinfo&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;dedication&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;abstract&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;body
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il n'y plus qu'à le personnaliser avec du code LaTeX pour qu'il réponde à nos
besoins :&lt;/p&gt;
&lt;pre class="code latex literal-block"&gt;
&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;head_prefix&lt;/span&gt;&lt;span class="c"&gt;% generated by Docutils &amp;lt;http://docutils.sourceforge.net/&amp;gt;
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{fixltx&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;e} &lt;/span&gt;&lt;span class="c"&gt;% LaTeX patches, \textsubscript
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{cmap} &lt;/span&gt;&lt;span class="c"&gt;% fix search and cut-and-paste in Acrobat
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;raccourcis&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;{fast&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;diagram}
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;french&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;{babel}
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{titlesec}
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;a&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="nb"&gt;paper,left&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;cm,right&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;cm,top&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;cm,bottom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="nb"&gt;cm&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;{geometry}
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;requirements
&lt;span class="c"&gt;%%% Custom LaTeX preamble
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;latex_preamble
&lt;/span&gt;&lt;span class="c"&gt;%%% User specified packages and stylesheets
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;stylesheet
&lt;span class="c"&gt;%%% Fallback definitions for Docutils-specific commands
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;fallbacks&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;pdfsetup
&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;titledata
&lt;/span&gt;&lt;span class="c"&gt;%%% Custom font
&lt;/span&gt;&lt;span class="nv"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{libertine}
&lt;/span&gt;&lt;span class="c"&gt;%%% Set numeration
&lt;/span&gt;&lt;span class="nv"&gt;\setcounter&lt;/span&gt;&lt;span class="nb"&gt;{secnumdepth}{&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="nb"&gt;}
&lt;/span&gt;&lt;span class="c"&gt;%%% Body
&lt;/span&gt;&lt;span class="nv"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{document}
&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;body&lt;span class="nb"&gt;_&lt;/span&gt;pre&lt;span class="nb"&gt;_&lt;/span&gt;docinfo&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;docinfo&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;dedication&lt;span class="s"&gt;$&lt;/span&gt;&lt;span class="nb"&gt;abstract&lt;/span&gt;&lt;span class="s"&gt;$&lt;/span&gt;body
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Je précise que l'ordre avec lequel vous insérer votre code et les variables est
important. Si on met la ligne &lt;tt class="docutils literal"&gt;\usepackage{libertine}&lt;/tt&gt; (qui change la police)
juste après les autres &lt;tt class="docutils literal"&gt;usepackage&lt;/tt&gt; le choix de ma police sera écrasée par
celle de Rst.&lt;/p&gt;
&lt;p&gt;Je propose un exemple plus complet en &lt;a class="reference external" href="//www.jujens.eu/static/rapport-rst-sphinx/template.tex"&gt;téléchargement&lt;/a&gt; (avec notamment une page
de garde personnalisée).&lt;/p&gt;
&lt;p&gt;On peut également utiliser les options &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--document-class&lt;/span&gt;&lt;/tt&gt; et
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;--document-options&lt;/span&gt;&lt;/tt&gt; pour personnaliser le document. Il existe bien d'autres
options, je vous laisse regarder la sortie de &lt;tt class="docutils literal"&gt;rst2latex &lt;span class="pre"&gt;-h&lt;/span&gt;&lt;/tt&gt; pour la liste
complète.&lt;/p&gt;
&lt;p&gt;On générera le fichier .tex avec :&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
rst2latex
rapport.rst --template=template.tex --documentclass=report --documentoptions=12pt
&lt;/pre&gt;
&lt;p&gt;Et pour le glossaire ? Ce n'est pas possible, faute de syntaxe approprié,
directement avec rst. Ça viendra peut être un jour, c'est sur la &lt;a class="reference external" href="http://docutils.sourceforge.net/docs/dev/todo.html"&gt;todo list des
dévoleppeurs&lt;/a&gt;. C'est là
que sphinx entre en jeu.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="sphinx"&gt;
&lt;h2&gt;Sphinx&lt;/h2&gt;
&lt;div class="section" id="id2"&gt;
&lt;h3&gt;Présentation&lt;/h3&gt;
&lt;p&gt;&lt;a class="reference external" href="http://sphinx-doc.org/"&gt;sphinx&lt;/a&gt; est un générateur de documentation pour
python. Il utilise la syntaxe rst et peut produire des documents HTML, pdf, des
pages man, etc. Il propose également des extensions à la syntaxe de base comme
&lt;tt class="docutils literal"&gt;term&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;glossary&lt;/tt&gt; pour un glossaire et quelques divergences. Par exemple,
la table des matières ne se génère plus avec &lt;tt class="docutils literal"&gt;.. contents::&lt;/tt&gt; mais avec
&lt;tt class="docutils literal"&gt;.. toctree::&lt;/tt&gt; et les inclusions de fichier se font avec
&lt;tt class="docutils literal"&gt;.. raw::&lt;/tt&gt;. Typiquement, on utilise un Makefile pour automatiser la
génération, Makefile que sphinx est capable de créer tout seul.&lt;/p&gt;
&lt;p&gt;Mais rassurez-vous, dans l'ensemble tout fonctionne quasiment comme avec
rst. Lorsque je suis passé de rst brut à sphinx, mon seul problème a été
l'utilisation des mes entêtes LaTeX personnalisées.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id4"&gt;
&lt;h3&gt;Rédiger son rapport&lt;/h3&gt;
&lt;p&gt;Il faut tout d'abord initialiser sphinx, avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;sphinx-quickstart&lt;/span&gt;&lt;/tt&gt;. Le programme
va alors vous poser plusieurs questions pour générer une configuration de base.&lt;/p&gt;
&lt;p&gt;Le rapport en lui même se rédige comme sous rst avec les mêmes possibilités
d'inclusion de fichiers. Attention toute fois, l'inclusion est relative au
Makefile alors qu'aupapravant, elle était relative au fichier d'inclusion.&lt;/p&gt;
&lt;p&gt;Lors de mon passage à sphinx, peu importe l'endroit où j'insérais la directive
&lt;tt class="docutils literal"&gt;.. toctree::&lt;/tt&gt; la table des matières se retrouvait en début de fichier alors
que je la voulais après l'introduction et le résumé. Qu'à cela ne tienne, la
directive &lt;tt class="docutils literal"&gt;.. raw::&lt;/tt&gt; m'a permit d'insérer la commande LaTeX
&lt;tt class="docutils literal"&gt;\tableofcontents&lt;/tt&gt; où je voulais.&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt; latex

         \tableofcontents
&lt;/pre&gt;
&lt;p&gt;Et pour le glossaire alors ? Rien de plus simple :&lt;/p&gt;
&lt;pre class="code rst literal-block"&gt;
J'ulitise le &lt;span class="na"&gt;:term:&lt;/span&gt;&lt;span class="nv"&gt;`CMS`&lt;/span&gt; &lt;span class="na"&gt;:term:&lt;/span&gt;&lt;span class="nv"&gt;`Drupal`&lt;/span&gt;

&lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="ow"&gt;glossary&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;

   CMS
     Acronyme de &lt;span class="ge"&gt;*Content Management System*&lt;/span&gt;, soit système de gestion de
     contenu.

   Drupal
     Un des &lt;span class="na"&gt;:term:&lt;/span&gt;&lt;span class="nv"&gt;`CMS`&lt;/span&gt; les plus connus et réputé. Il est utilisé par de
     nombreuses entreprises et institutions à travers le monde.
&lt;/pre&gt;
&lt;p&gt;Le seul point qui m'a posé problème c'est la configuration. Elle est quasi
intégralement géré pour l'export LaTeX par le dictionnaire
&lt;tt class="docutils literal"&gt;latex_elements&lt;/tt&gt;. Par exemple, pour moi :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;preamble&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;'''\usepackage&lt;/span&gt;&lt;span class="si"&gt;{fixltx2e}&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="si"&gt;% La&lt;/span&gt;&lt;span class="s1"&gt;TeX patches, \textsubscript
\usepackage&lt;/span&gt;&lt;span class="si"&gt;{cmap}&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="si"&gt;% f&lt;/span&gt;&lt;span class="s1"&gt;ix search and cut-and-paste in Acrobat
\usepackage[raccourcis]{fast-diagram}
\usepackage&lt;/span&gt;&lt;span class="si"&gt;{titlesec}&lt;/span&gt;&lt;span class="s1"&gt;
\usepackage[a4paper,left=2cm,right=2cm,top=2cm,bottom=2cm]&lt;/span&gt;&lt;span class="si"&gt;{geometry}&lt;/span&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;span class="si"&gt;%%&lt;/span&gt;&lt;span class="s1"&gt;% Redifined titleformat
\setlength{\parindent}&lt;/span&gt;&lt;span class="si"&gt;{0cm}&lt;/span&gt;&lt;span class="s1"&gt;
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex}
\newcommand{\hsp}{\hspace&lt;/span&gt;&lt;span class="si"&gt;{20pt}&lt;/span&gt;&lt;span class="s1"&gt;}
\newcommand{\HRule}{\rule{\linewidth}&lt;/span&gt;&lt;span class="si"&gt;{0.5mm}&lt;/span&gt;&lt;span class="s1"&gt;}
\titleformat{\chapter}[hang]{\Huge\bfseries\sffamily}{\thechapter\hsp}&lt;/span&gt;&lt;span class="si"&gt;{0pt}&lt;/span&gt;&lt;span class="s1"&gt;{\Huge\bfseries\sffamily}
&lt;/span&gt;&lt;span class="si"&gt;%%&lt;/span&gt;&lt;span class="s1"&gt;% Custom font
\usepackage&lt;/span&gt;&lt;span class="si"&gt;{libertine}&lt;/span&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;span class="si"&gt;%%&lt;/span&gt;&lt;span class="s1"&gt;% Set numeration
\setcounter&lt;/span&gt;&lt;span class="si"&gt;{secnumdepth}{3}&lt;/span&gt;&lt;span class="s1"&gt;
'''&lt;/span&gt;
&lt;span class="n"&gt;latex_elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;# The paper size ('letterpaper' or 'a4paper').&lt;/span&gt;
&lt;span class="s1"&gt;'papersize'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'a4paper'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;# The font size ('10pt', '11pt' or '12pt').&lt;/span&gt;
&lt;span class="s1"&gt;'pointsize'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'12pt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;# Babel for french&lt;/span&gt;
&lt;span class="s1"&gt;'babel'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;usepackage[french]&lt;/span&gt;&lt;span class="si"&gt;{babel}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;# Additional stuff for the LaTeX preamble.&lt;/span&gt;
&lt;span class="s1"&gt;'preamble'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;preamble&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;# No default title&lt;/span&gt;
&lt;span class="s1"&gt;'maketitle'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;# No default toc&lt;/span&gt;
&lt;span class="s1"&gt;'tableofcontents'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;La classe du document se spécifie dans la variable &lt;tt class="docutils literal"&gt;latex_documents&lt;/tt&gt; :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;latex_documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rapport'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Rapport.tex'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Rapport de stage 2A'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'Julien Enselme'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'manual'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Les classes habituelles de LaTeX ne sont pas compatibles avec sphinx. Il faut
soit utiliser celles par défaut (manual pour un rapport ou how-to pour un
article) soit les personnaliser.&lt;/p&gt;
&lt;p&gt;Je pense qu'à partir de cet exemple, vous pourrez subvenir à vos besoins
facilement. Sinon, vous pouvez toujours poster un commentaire.&lt;/p&gt;
&lt;p&gt;Vous trouverez dans &lt;a class="reference external" href="http://sphinx-doc.org/config.html#options-for-latex-output"&gt;la documentation complète&lt;/a&gt; toutes des
options que je n'ai pas pu vous présenter ici.&lt;/p&gt;
&lt;p&gt;Je vous propose également un &lt;a class="reference external" href="//www.jujens.eu/static/rapport-rst-sphinx/conf.py"&gt;un fichier de configuration complet&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;J'espère vous avoir convaincu d'utiliser la puissance et la légèreté de rst et
sphinx pour rédiger vos rapports, avec un peu de LaTeX brut par endroit (faute
de mieux) en lieu et place des WYSIWYG.&lt;/p&gt;
&lt;p&gt;Même si abandonner LaTeX peut faire un peu peur et que la configuration de
sphinx est un peu ardue sans exemple complet, je ne regrette pas mon choix et
suis bien content d'utiliser rst (même si je dois reconnaître qu'il est dommage
que sphinx ne puisse utiliser les classes de base de LaTeX) !&lt;/p&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="python"></category><category term="Rst"></category><category term="sphinx"></category></entry><entry><title>Comment supprimer toutes les tables mysql qui contiennent un motif</title><link href="//www.jujens.eu/posts/2014/Jul/30/supprimer_plusieurs_tables_mysql_motif/" rel="alternate"></link><published>2014-07-30T00:00:00+02:00</published><updated>2014-07-30T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-07-30:/posts/2014/Jul/30/supprimer_plusieurs_tables_mysql_motif/</id><summary type="html">&lt;p&gt;Récemment, j'ai eu besoin de faire du ménage dans les tables d'une base de
données. Toutes les tables à supprimer commençaient par le même
motif. Malheureusement, mysql ne permet pas d'utiliser le jocker &lt;tt class="docutils literal"&gt;%&lt;/tt&gt; dans une
requête &lt;tt class="docutils literal"&gt;DROP&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Heureusement la solution est simple. Il suffit de lister toutes les tables ayant …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Récemment, j'ai eu besoin de faire du ménage dans les tables d'une base de
données. Toutes les tables à supprimer commençaient par le même
motif. Malheureusement, mysql ne permet pas d'utiliser le jocker &lt;tt class="docutils literal"&gt;%&lt;/tt&gt; dans une
requête &lt;tt class="docutils literal"&gt;DROP&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Heureusement la solution est simple. Il suffit de lister toutes les tables ayant
ce motif grâce à la requête &lt;tt class="docutils literal"&gt;SHOW TABLES LIKE 'motif%'&lt;/tt&gt;. Reste à boucler sur
ces tables pour les supprimer. D'où le code suivant :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="nv"&gt;motif&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;del_
&lt;span class="k"&gt;for&lt;/span&gt; table in &lt;span class="k"&gt;$(&lt;/span&gt;mysql database -NBe &lt;span class="s2"&gt;&amp;quot;SHOW TABLES LIKE '&lt;/span&gt;&lt;span class="nv"&gt;$motif&lt;/span&gt;&lt;span class="s2"&gt;%'&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  mysql database &lt;span class="s2"&gt;&amp;quot;DROP TABLE &lt;/span&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;L'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-N&lt;/span&gt;&lt;/tt&gt; de mysql masque les entêtes de colonnes et l'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-B&lt;/span&gt;&lt;/tt&gt;
permet d'avoir un résultat brut, exploitable dans la boucle.&lt;/p&gt;
&lt;p&gt;On peut également faire &lt;a class="reference external" href="//www.jujens.eu/static/supprimer_plusieurs_tables_mysql_motif/mysql_drop_table_like.sh"&gt;le script plus générique suivant&lt;/a&gt; :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
&lt;span class="ch"&gt;#!/usr/bin/bash
&lt;/span&gt;
&lt;span class="nv"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;mysql_drop_table_like [options] database pattern

Drop all the mysql tables in database that starts with pattern.

-h: host
-u: user
-pPASSWD: give password
-P: prompt for password
&amp;quot;&lt;/span&gt;

usage&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="nv"&gt;$help&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;pflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="nv"&gt;Pflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="nv"&gt;uflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;
&lt;span class="nv"&gt;hflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;getopts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;:h:u:p:P&amp;quot;&lt;/span&gt; opt
&lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$opt&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; in
        h&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;hflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        u&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;uflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        p&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;passwd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;pflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        P&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nv"&gt;Pflag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;true&lt;span class="p"&gt;;;&lt;/span&gt;
        :&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Option -&lt;/span&gt;&lt;span class="nv"&gt;$OPTARG&lt;/span&gt;&lt;span class="s2"&gt; requires an argument.&amp;quot;&lt;/span&gt; &amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
            usage&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
        &lt;span class="se"&gt;\?&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            usage&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="k"&gt;$((&lt;/span&gt;OPTIND-1&lt;span class="k"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# To get the 1st positional argument with $1
&lt;/span&gt;
&lt;span class="c1"&gt;# Check that we have at least 2 positional arguments
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$#&lt;/span&gt; -lt &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Number of positional arguments insuffisant.&amp;quot;&lt;/span&gt;
    usage
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c1"&gt;# Cannot provide and ask for password
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$Pflag&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$pflag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Cannot provide and ask for password.&amp;quot;&lt;/span&gt;
    usage
    &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$hflag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-h &lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$pflag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nv"&gt;PASSWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-p&lt;/span&gt;&lt;span class="nv"&gt;$passwd&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$Pflag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nv"&gt;PASSWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-p&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$uflag&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;-u &lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nv"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;mysql &lt;/span&gt;&lt;span class="nv"&gt;$HOST&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$PASSWD&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; table in &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$mysql&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; -NBe &lt;span class="s2"&gt;&amp;quot;SHOW TABLES LIKE '&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;%'&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="nv"&gt;$mysql&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;quot;DROP TABLE &lt;/span&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Blog"></category></entry><entry><title>Créer des pages d'erreurs personnalisées pour son blog pelican</title><link href="//www.jujens.eu/posts/2014/Jun/29/404-personnalisee-pelican/" rel="alternate"></link><published>2014-06-29T00:00:00+02:00</published><updated>2014-06-29T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-06-29:/posts/2014/Jun/29/404-personnalisee-pelican/</id><summary type="html">&lt;p&gt;Rien de très compliqué. Par exemple, pour les erreurs 404, il suffit :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;de créer une page 404.rst avec le status &lt;em&gt;hidden&lt;/em&gt; :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="nc"&gt;:title:&lt;/span&gt; 404
&lt;span class="nc"&gt;:status:&lt;/span&gt; hidden

La page demandée n'existe pas. Vous pouvez revenir à &lt;span class="s"&gt;`l'accueil &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;http://www.jujens.eu&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;.
&lt;/pre&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;d'ajouter une ligne dans sa configuration nginx :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;404 …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;Rien de très compliqué. Par exemple, pour les erreurs 404, il suffit :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;de créer une page 404.rst avec le status &lt;em&gt;hidden&lt;/em&gt; :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code rst literal-block"&gt;
&lt;span class="nc"&gt;:title:&lt;/span&gt; 404
&lt;span class="nc"&gt;:status:&lt;/span&gt; hidden

La page demandée n'existe pas. Vous pouvez revenir à &lt;span class="s"&gt;`l'accueil &lt;/span&gt;&lt;span class="si"&gt;&amp;lt;http://www.jujens.eu&amp;gt;&lt;/span&gt;&lt;span class="s"&gt;`_&lt;/span&gt;.
&lt;/pre&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;d'ajouter une ligne dans sa configuration nginx :&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;error_page&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="s"&gt;/pages/404.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et voilà ! Vous pouvez évidement faire de même pour les autres erreurs, mais je
doute qu'elle soit aussi courante.&lt;/p&gt;
</content><category term="Auto-hébergement"></category><category term="nginx"></category><category term="pelican"></category></entry><entry><title>Faire du https avec nginx</title><link href="//www.jujens.eu/posts/2014/Jun/29/nginx-https/" rel="alternate"></link><published>2014-06-29T00:00:00+02:00</published><updated>2015-09-23T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-06-29:/posts/2014/Jun/29/nginx-https/</id><summary type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-les-certificats" id="id1"&gt;Générer les certificats&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#preparation" id="id2"&gt;Préparation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#creation-de-l-autorite" id="id3"&gt;Création de l'autorité&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-le-csr-certificate-signing-request" id="id4"&gt;Générer le CSR (Certificate Signing Request)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#retirer-la-passphrase-de-la-cle" id="id5"&gt;Retirer la passphrase de la clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-le-certificat-auto-signe" id="id6"&gt;Générer le certificat auto-signé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-la-liste-de-revocation-de-certificats-crl" id="id7"&gt;Générer la liste de révocation de certificats (CRL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-nginx" id="id8"&gt;Configurer nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#importer-le-certificat-au-niveau-systeme" id="id9"&gt;Importer le certificat au niveau système&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#linux" id="id10"&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#windows" id="id11"&gt;Windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#source" id="id12"&gt;Source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Dans cet article, je ne vais pas …&lt;/p&gt;</summary><content type="html">&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-les-certificats" id="id1"&gt;Générer les certificats&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#preparation" id="id2"&gt;Préparation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#creation-de-l-autorite" id="id3"&gt;Création de l'autorité&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-le-csr-certificate-signing-request" id="id4"&gt;Générer le CSR (Certificate Signing Request)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#retirer-la-passphrase-de-la-cle" id="id5"&gt;Retirer la passphrase de la clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-le-certificat-auto-signe" id="id6"&gt;Générer le certificat auto-signé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#generer-la-liste-de-revocation-de-certificats-crl" id="id7"&gt;Générer la liste de révocation de certificats (CRL)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-nginx" id="id8"&gt;Configurer nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#importer-le-certificat-au-niveau-systeme" id="id9"&gt;Importer le certificat au niveau système&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#linux" id="id10"&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#windows" id="id11"&gt;Windows&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#source" id="id12"&gt;Source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Dans cet article, je ne vais pas du tout rentrer dans les détails de la
cryptographie ou de SSL, TLS, https, … Je présente juste comment faire
rapidement du https avec nginx. Si vous voulez plus d'informations (ce qui est
une bonne idée), je vous invite à consulter le web.&lt;/p&gt;
&lt;p&gt;Pour faire du https, nous avons besoin de certificats et de modifier la
configuration du serveur web. Nous allons générer nos certificats. &lt;strong&gt;Ils seront
auto-signés. Quand vous vous y connecterez, vous aurez donc un message d'erreur
vous disant que la connection n'est pas de confiance (sauf si vous ajoutez
manuellement le certificat à ceux de confiances au niveau système).&lt;/strong&gt; Ce type de
certificat est donc à réserver à son propre usage.&lt;/p&gt;
&lt;div class="section" id="generer-les-certificats"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Générer les certificats&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="preparation"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id2"&gt;Préparation&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pour générer les certificats, nous avons besoin d'OpenSSL. Ce logiciel est
présent dans toutes les distributions GNU/Linux dignes de ce nom. Installez le
de la façon habituelle.&lt;/p&gt;
&lt;p&gt;Nous allons placer les certificats dans un dossier dédié. Ce dossier contiendra
3 sous dossiers :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;private pour les clés de notre CA (Certificate Authority)&lt;/li&gt;
&lt;li&gt;certs pour les certificats&lt;/li&gt;
&lt;li&gt;newcerts pour les nouveaux cerfiticats&lt;/li&gt;
&lt;li&gt;crl pour le Ceritificate Revocation List (crl)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On ajoute les deux fichiers :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;index.txt qui est utilisé par OpenSSL pour stocker les informations sur les
certificats&lt;/li&gt;
&lt;li&gt;serial qui contint le numéro des certificats crées. Il est automatiquement
incrémenté.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Par exemple :&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
mkdir -p /root/certs/&lt;span class="o"&gt;{&lt;/span&gt;private,certs,newcerts,crl&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /root/certs
touch index.txt
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;01&amp;quot;&lt;/span&gt; &amp;gt; serial
&lt;/pre&gt;
&lt;p&gt;Toutes les commandes seront à exécuter depuis ce dossier.&lt;/p&gt;
&lt;p&gt;On crée le fichier de configuration d'OpenSSL afin de faciliter la génération
des clés de la CA dans ca.cnf :&lt;/p&gt;
&lt;pre class="code cfg literal-block"&gt;
&lt;span class="k"&gt;[ ca ]&lt;/span&gt;
&lt;span class="na"&gt;default_ca&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;CA_default            # The default ca section&lt;/span&gt;


&lt;span class="k"&gt;[ CA_default ]&lt;/span&gt;

&lt;span class="na"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;. # Where everything is kept&lt;/span&gt;
&lt;span class="na"&gt;certs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/certs # Where the issued certs are kept&lt;/span&gt;
&lt;span class="na"&gt;crl_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/crl # Where the issued crl are kept&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/index.txt # database index file.&lt;/span&gt;
&lt;span class="c1"&gt;#unique_subject = no # Set to 'no' to allow creation of&lt;/span&gt;
&lt;span class="c1"&gt;# several ctificates with same subject.&lt;/span&gt;
&lt;span class="na"&gt;new_certs_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/newcerts # default place for new certs.&lt;/span&gt;

&lt;span class="na"&gt;certificate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/certs/ca.crt # The CA certificate&lt;/span&gt;
&lt;span class="na"&gt;serial&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/serial # The current serial number&lt;/span&gt;
&lt;span class="c1"&gt;#crlnumber = $dir/crlnumber # the current crl number&lt;/span&gt;
&lt;span class="c1"&gt;# must be commented out to leave a V1 CRL&lt;/span&gt;
&lt;span class="na"&gt;crl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/crl.pem # The current CRL&lt;/span&gt;
&lt;span class="na"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$dir/private/ca.key # The private key&lt;/span&gt;
&lt;span class="na"&gt;default_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;365 # how long to certify for&lt;/span&gt;
&lt;span class="na"&gt;default_crl_days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;365 # how long before next CRL&lt;/span&gt;
&lt;span class="na"&gt;default_md&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;sha512 # use SHA-512 by default&lt;/span&gt;
&lt;span class="na"&gt;x509_extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;usr_cert&lt;/span&gt;


&lt;span class="k"&gt;[ req ]&lt;/span&gt;
&lt;span class="na"&gt;distinguished_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;req_distinguished_name&lt;/span&gt;


&lt;span class="k"&gt;[ req_distinguished_name ]&lt;/span&gt;
&lt;span class="na"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Country Name (2 letter code)&lt;/span&gt;
&lt;span class="na"&gt;countryName_default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;FR&lt;/span&gt;
&lt;span class="na"&gt;countryName_min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;countryName_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2&lt;/span&gt;

&lt;span class="na"&gt;stateOrProvinceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;State or Province Name (full name)&lt;/span&gt;
&lt;span class="na"&gt;stateOrProvinceName_default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;PACA&lt;/span&gt;

&lt;span class="na"&gt;localityName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Locality Name (eg, city)&lt;/span&gt;
&lt;span class="na"&gt;localityName_default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;MARSEILLE&lt;/span&gt;

&lt;span class="na"&gt;0.organizationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Organization Name (eg, company)&lt;/span&gt;
&lt;span class="na"&gt;0.organizationName_default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;jujens.eu&lt;/span&gt;

&lt;span class="na"&gt;organizationalUnitName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Organizational Unit Name (eg, section)&lt;/span&gt;
&lt;span class="c1"&gt;#organizationalUnitName_default =&lt;/span&gt;

&lt;span class="na"&gt;commonName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Common Name (eg, YOUR name)&lt;/span&gt;
&lt;span class="na"&gt;commonName_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64&lt;/span&gt;

&lt;span class="na"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;Email Address&lt;/span&gt;
&lt;span class="na"&gt;emailAddress_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64&lt;/span&gt;
&lt;span class="na"&gt;default_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;365 # how long to certify for&lt;/span&gt;


&lt;span class="k"&gt;[ policy_anything ]&lt;/span&gt;
&lt;span class="na"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;
&lt;span class="na"&gt;stateOrProvinceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;
&lt;span class="na"&gt;localityName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;
&lt;span class="na"&gt;organizationName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;
&lt;span class="na"&gt;organizationalUnitName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;
&lt;span class="na"&gt;commonName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;supplied&lt;/span&gt;
&lt;span class="na"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;optional&lt;/span&gt;


&lt;span class="k"&gt;[ usr_cert ]&lt;/span&gt;
&lt;span class="na"&gt;basicConstraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;CA:TRUE&lt;/span&gt;
&lt;span class="na"&gt;crlDistributionPoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;URI:http://dl.jujens.eu/jujens-eu.crl&lt;/span&gt;


&lt;span class="k"&gt;[ v3_ca ]&lt;/span&gt;


&lt;span class="c1"&gt;# Extensions for a typical CA&lt;/span&gt;


&lt;span class="c1"&gt;# PKIX recommendation.&lt;/span&gt;

&lt;span class="na"&gt;subjectKeyIdentifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;hash&lt;/span&gt;

&lt;span class="na"&gt;authorityKeyIdentifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;keyid:always,issuer&lt;/span&gt;

&lt;span class="c1"&gt;# This is what PKIX recommends but some broken software chokes on critical&lt;/span&gt;
&lt;span class="c1"&gt;# extensions.&lt;/span&gt;
&lt;span class="c1"&gt;#basicConstraints = critical,CA:true&lt;/span&gt;
&lt;span class="c1"&gt;# So we do this instead.&lt;/span&gt;
&lt;span class="na"&gt;basicConstraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;CA:true&lt;/span&gt;

&lt;span class="c1"&gt;# Key usage: this is typical for a CA certificate. However since it will&lt;/span&gt;
&lt;span class="c1"&gt;# prevent it being used as an test self-signed certificate it is best&lt;/span&gt;
&lt;span class="c1"&gt;# left out by default.&lt;/span&gt;
&lt;span class="c1"&gt;# keyUsage = cRLSign, keyCertSign&lt;/span&gt;

&lt;span class="c1"&gt;# Some might want this also&lt;/span&gt;
&lt;span class="c1"&gt;# nsCertType = sslCA, emailCA&lt;/span&gt;

&lt;span class="c1"&gt;# Include email address in subject alt name: another PKIX recommendation&lt;/span&gt;
&lt;span class="c1"&gt;# subjectAltName=email:copy&lt;/span&gt;
&lt;span class="c1"&gt;# Copy issuer details&lt;/span&gt;
&lt;span class="c1"&gt;# issuerAltName=issuer:copy&lt;/span&gt;

&lt;span class="c1"&gt;# DER hex encoding of an extension: beware experts only!&lt;/span&gt;
&lt;span class="c1"&gt;# obj=DER:02:03&lt;/span&gt;
&lt;span class="c1"&gt;# Where 'obj' is a standard or added object&lt;/span&gt;
&lt;span class="c1"&gt;# You can even override a supported extension:&lt;/span&gt;
&lt;span class="c1"&gt;# basicConstraints= critical, DER:30:03:01:01:FF&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note :&lt;/strong&gt; le champ commonName de la section &lt;em&gt;policy_anything&lt;/em&gt; est
indispensable, il ne peut donc pas avoir la valeur &lt;tt class="docutils literal"&gt;optional&lt;/tt&gt;. Vous pouvez
rendre obligatoire n'importe quel autre champ à la création d'un certificat.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creation-de-l-autorite"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;Création de l'autorité&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Nous créons le certificat de l'autorité qui servira à signer les autres
certificats et la clé associé. L'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-nodes&lt;/span&gt;&lt;/tt&gt; permet de ne pas chiffrer la
clé privée.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
openssl req -new -x509 -extensions v3_ca -newkey rsa:4096 -keyout private/ca.key -out certs/ca.crt -config ca.conf -days &lt;span class="m"&gt;730&lt;/span&gt;

Generating a &lt;span class="m"&gt;4096&lt;/span&gt; bit RSA private key
............................................................................................................................++
....................................................................................................................................................................................................................................................................................................................................................++
writing new private key to &lt;span class="s1"&gt;'private/ca.key'&lt;/span&gt;
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &lt;span class="s1"&gt;'.'&lt;/span&gt;, the field will be left blank.
-----
Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;FR&lt;span class="o"&gt;]&lt;/span&gt;:
State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;PACA&lt;span class="o"&gt;]&lt;/span&gt;:
Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;MARSEILLE&lt;span class="o"&gt;]&lt;/span&gt;:
Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;jujens.eu&lt;span class="o"&gt;]&lt;/span&gt;:
Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
Common Name &lt;span class="o"&gt;(&lt;/span&gt;eg, YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:jujens.eu
Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:admin&amp;#64;jujens.eu
&lt;/pre&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;req est la commande de génération de certificat&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-new&lt;/span&gt;&lt;/tt&gt; pour créer un nouveau certificat&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-x509&lt;/span&gt;&lt;/tt&gt; pour créer un certificat auto signé ce qui permet de créer le
certificat d'une CA (ou de faire un certificat de test).&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-extensions&lt;/span&gt; v3_ca&lt;/tt&gt; pour utiliser l'extension CA.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-newkey&lt;/span&gt; rsa:4096&lt;/tt&gt; pour générer une clé rsa de 4096 bits&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-keyout&lt;/span&gt; private/ca.key&lt;/tt&gt; dans quel fichier écrire la clé&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-out&lt;/span&gt; certs/ca.crt&lt;/tt&gt; dans quel fichier écrire le certificat&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-config&lt;/span&gt; ca.conf&lt;/tt&gt; pour utiliser notre fichier de configuration&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Ne perdez pas la passphrase (que vous pouvez choisir comme vous voulez).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;L'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-pasout&lt;/span&gt; pass:x&lt;/tt&gt; permet de ne pas avoir à entrer de passphrase,
openssl va utiliser la passphrase passée en paramètre.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="generer-le-csr-certificate-signing-request"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Générer le CSR (Certificate Signing Request)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Puisque le certificat va être utilisé par nginx, il ne faut pas qu'il soit
protégé par une passphrase.  On utilise presque la même commande que tout à
l'heure.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
openssl req -new -nodes -newkey rsa:4096 -keyout private/jujens-eu.key -out certs/jujens-eu.csr -config ca.conf -set_serial &lt;span class="m"&gt;10&lt;/span&gt;

Generating a &lt;span class="m"&gt;4096&lt;/span&gt; bit RSA private key
.++
...............................................................................................++
writing new private key to &lt;span class="s1"&gt;'private/jujens-eu.key'&lt;/span&gt;
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &lt;span class="s1"&gt;'.'&lt;/span&gt;, the field will be left blank.
-----
Country Name &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;FR&lt;span class="o"&gt;]&lt;/span&gt;:
State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;PACA&lt;span class="o"&gt;]&lt;/span&gt;:
Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;MARSEILLE&lt;span class="o"&gt;]&lt;/span&gt;:
Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;jujens.eu&lt;span class="o"&gt;]&lt;/span&gt;:
Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:
Common Name &lt;span class="o"&gt;(&lt;/span&gt;eg, YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:*.jujens.eu
Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:admin&amp;#64;jujens.eu
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Le champ Common Name doit correspondre au nom de domaine du serveur. Wildcard autorisé.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="retirer-la-passphrase-de-la-cle"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Retirer la passphrase de la clé&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;L'inconvénient que l'on a avec cette clé chiffrée avec une passphrase est qu'il
faut entrer cette passphrase à chaque fois que l'on démarre le serveur. Ce qui
n'est ni pratique ni forcément possible (reboot, crash, …). On peut retirer la
passphrase de la clé. Cela peut présenter des risques de sécurité. Cette version
de la clé ne doit donc être accessible qu'à l'utilisateur root.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
[jenselme&amp;#64;fastolfe tmp]% cp server.key server.key.org

[jenselme&amp;#64;fastolfe tmp]% openssl rsa -in server.key.org -out server.key
Enter pass phrase for server.key.org:
writing RSA key
&lt;/pre&gt;
&lt;p&gt;Vous pouvez également utiliser l'option &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-passin&lt;/span&gt; pass:x&lt;/tt&gt; pour passer la clé à
la commande.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="generer-le-certificat-auto-signe"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Générer le certificat auto-signé&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;On génère enfin le certificat auto-signé.&lt;/p&gt;
&lt;pre class="code bash literal-block"&gt;
openssl ca -extensions usr_cert -config ca.conf -policy policy_anything -out certs/jujens-eu.crt -infiles certs/jujens-eu.csr

Using configuration from ca.conf
Check that the request matches the signature
Signature ok
The Subject&lt;span class="s1"&gt;'s Distinguished Name is as follows
countryName           :PRINTABLE:'&lt;/span&gt;FR&lt;span class="s1"&gt;'
stateOrProvinceName   :ASN.1 12:'&lt;/span&gt;PACA&lt;span class="s1"&gt;'
localityName          :ASN.1 12:'&lt;/span&gt;MARSEILLE&lt;span class="s1"&gt;'
organizationName      :ASN.1 12:'&lt;/span&gt;jujens.eu&lt;span class="s1"&gt;'
commonName            :ASN.1 12:'&lt;/span&gt;*.jujens.eu&lt;span class="s1"&gt;'
emailAddress          :IA5STRING:'&lt;/span&gt;admin&amp;#64;jujens.eu&lt;span class="err"&gt;'&lt;/span&gt;
Certificate is to be certified &lt;span class="k"&gt;until&lt;/span&gt; Aug &lt;span class="m"&gt;20&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;:24:46 &lt;span class="m"&gt;2016&lt;/span&gt; GMT &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;365&lt;/span&gt; days&lt;span class="o"&gt;)&lt;/span&gt;
Sign the certificate? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;:y


&lt;span class="m"&gt;1&lt;/span&gt; out of &lt;span class="m"&gt;1&lt;/span&gt; certificate requests certified, commit? &lt;span class="o"&gt;[&lt;/span&gt;y/n&lt;span class="o"&gt;]&lt;/span&gt;y
Write out database with &lt;span class="m"&gt;1&lt;/span&gt; new entries
Data Base Updated
&lt;/pre&gt;
&lt;p&gt;Vous pouvez vérifier votre certificat avec : &lt;tt class="docutils literal"&gt;openssl x509 &lt;span class="pre"&gt;-noout&lt;/span&gt; &lt;span class="pre"&gt;-text&lt;/span&gt; &lt;span class="pre"&gt;-in&lt;/span&gt;
server.crt&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="generer-la-liste-de-revocation-de-certificats-crl"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id7"&gt;Générer la liste de révocation de certificats (CRL)&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cette liste contient des informations sur quels certificats ont été
révoqué. Certaines applications (comme les navigateurs web) vont périodiquement
télécharger ce fichier pour savoir si un certificat est toujours valide. Si ce
téléchargement échoue, le certificat sera considéré comme étant invalide.&lt;/p&gt;
&lt;p&gt;La période au bout de laquelle la liste est téléchargée est définie par l'option
&lt;tt class="docutils literal"&gt;default_crl_days&lt;/tt&gt; de la section &lt;tt class="docutils literal"&gt;CA_default&lt;/tt&gt; dans la
configuration. L'adresse où le CRL est disponible est elle définie dans la
section &lt;tt class="docutils literal"&gt;usr_cert&lt;/tt&gt; avec la clé &lt;tt class="docutils literal"&gt;crlDistributionPoints&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Si vous ne voulez pas gérer ce paramètre, configurer simplement la durée du crl
comme étant égale ou supérieure à la durée du certificat.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
openssl ca -config ca.conf -gencrl -out crl/jujens-eu.crl
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-nginx"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id8"&gt;Configurer nginx&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Pour rediriger le trafic vers https, on utilise une rewrite rule :&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;ttrss.jujens.eu&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/framanews&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$server_name$request_uri?&lt;/span&gt; &lt;span class="s"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;On ajoute ensuite une entrée serveur qui écoute sur le port 443 et on donne les
chemins des certificats. Le reste est identique à la configuration http
&amp;quot;standard&amp;quot;.&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;ttrss.jujens.eu&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/framanews&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;ssl_session_cache&lt;/span&gt; &lt;span class="s"&gt;shared:SSL:10m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.1&lt;/span&gt; &lt;span class="s"&gt;TLSv1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt; &lt;span class="s"&gt;ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="s"&gt;/root/certs/certs/jujens-eu.crt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="s"&gt;/root/certs/private/jujens-eu.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

       &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="s"&gt;\.php&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="s"&gt;unix:/var/run/php5-fpm.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;SCRIPT_FILENAME&lt;/span&gt; &lt;span class="nv"&gt;$document_root$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
           &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;L'option &lt;tt class="docutils literal"&gt;ssl_prefer_server_ciphers&lt;/tt&gt; force l'utilisation d'un algorithme
donné par le serveur (par défaut, c'est la préférence du client qui est
importante).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="importer-le-certificat-au-niveau-systeme"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id9"&gt;Importer le certificat au niveau système&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="linux"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id10"&gt;Linux&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Récupérer le certificat de votre autorité (&lt;tt class="docutils literal"&gt;ca.crt&lt;/tt&gt;) et lancer :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
trust anchor Downloads/ca.crt
update-ca-trust
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="windows"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id11"&gt;Windows&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Exportez le certificat puis double cliquez sur celui-ci pour lancer la procédure
d'installation. Laissez toutes les options avec les valeurs par défaut.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="source"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id12"&gt;Source&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Certificats (en anglais) :
&lt;a class="reference external" href="http://www.akadia.com/services/ssh_test_certificate.html"&gt;http://www.akadia.com/services/ssh_test_certificate.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CA (en français) : &lt;a class="reference external" href="http://jeyg.info/des-certificats-signes-par-votre-autorite-de-certification-avec-openssl/"&gt;http://jeyg.info/des-certificats-signes-par-votre-autorite-de-certification-avec-openssl/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Auto-hébergement"></category><category term="nginx"></category></entry><entry><title>Comment sauvegarder une base de données PostgreSQL</title><link href="//www.jujens.eu/posts/2014/Jun/29/sauvegarder-base-donnees-postgresql/" rel="alternate"></link><published>2014-06-29T00:00:00+02:00</published><updated>2014-06-29T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-06-29:/posts/2014/Jun/29/sauvegarder-base-donnees-postgresql/</id><summary type="html">&lt;p&gt;Je vous propose une solution pour vous aider à sauvegarder votre base de données
PostgreSQL. La commande est &lt;tt class="docutils literal"&gt;pg_dump&lt;/tt&gt;. Elle prend comme argument (au minimum)
:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Le nom d'utilisateur&lt;/li&gt;
&lt;li&gt;Le mot de passe&lt;/li&gt;
&lt;li&gt;Le nom de la base de données&lt;/li&gt;
&lt;li&gt;L'adresse IP du serveur&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Donc la commande de base pour sauvegarder …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Je vous propose une solution pour vous aider à sauvegarder votre base de données
PostgreSQL. La commande est &lt;tt class="docutils literal"&gt;pg_dump&lt;/tt&gt;. Elle prend comme argument (au minimum)
:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Le nom d'utilisateur&lt;/li&gt;
&lt;li&gt;Le mot de passe&lt;/li&gt;
&lt;li&gt;Le nom de la base de données&lt;/li&gt;
&lt;li&gt;L'adresse IP du serveur&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Donc la commande de base pour sauvegarder une base de données est :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
pg_dump -h 127.0.0.1 -U owncloud -WMDP owncloud
&lt;/pre&gt;
&lt;p&gt;Le problème est que l'on doit fournir le mot de passe à chaque
fois. Heureusement, il y a une autre solution : le fichier .pgpass. Dans votre
home, créer un fichier &lt;tt class="docutils literal"&gt;.pgpass&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Chaque ligne de ce fichier contient les informations sur une base de données
sous la forme :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
IP:Port:Database:Username:Password
&lt;/pre&gt;
&lt;p&gt;Soit par exemple :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
127.0.0.1:5432:owncloud:owncloud:MPD
&lt;/pre&gt;
&lt;p&gt;La sauvegarde se lance ensuite avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
pg_dump -h 127.0.0.1 -U owncloud owncloud
&lt;/pre&gt;
&lt;p&gt;Reste à mettre la commande dans le &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/Crontab#Syntaxe_de_la_table"&gt;crontab&lt;/a&gt;.&lt;/p&gt;
</content><category term="Auto-hébergement"></category><category term="PostgreSQL"></category><category term="backup"></category><category term="Bash/Shell"></category></entry><entry><title>Comment installer framanews sur son serveur avec PostgreSQL et nginx</title><link href="//www.jujens.eu/posts/2014/Jun/14/installer-framanews/" rel="alternate"></link><published>2014-06-14T00:00:00+02:00</published><updated>2014-06-14T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-06-14:/posts/2014/Jun/14/installer-framanews/</id><summary type="html">&lt;p&gt;&lt;a class="reference external" href="https://framanews.org/"&gt;Framanews&lt;/a&gt; est un fork de &lt;a class="reference external" href="http://tt-rss.org/redmine/projects/tt-rss/wiki"&gt;ttrss&lt;/a&gt;, un lecteur de flux RSS en
ligne. Il vous permet donc de consulter vos flux, de vous y abonner, …
directement depuis un navigateur, où que vous soyez. Il dispose aussi d'une
&lt;a class="reference external" href="http://tt-rss.org/redmine/projects/tt-rss-android/wiki"&gt;application Android&lt;/a&gt;.
Il est évidement possible d'importer un fichier opml existant pour garder …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a class="reference external" href="https://framanews.org/"&gt;Framanews&lt;/a&gt; est un fork de &lt;a class="reference external" href="http://tt-rss.org/redmine/projects/tt-rss/wiki"&gt;ttrss&lt;/a&gt;, un lecteur de flux RSS en
ligne. Il vous permet donc de consulter vos flux, de vous y abonner, …
directement depuis un navigateur, où que vous soyez. Il dispose aussi d'une
&lt;a class="reference external" href="http://tt-rss.org/redmine/projects/tt-rss-android/wiki"&gt;application Android&lt;/a&gt;.
Il est évidement possible d'importer un fichier opml existant pour garder tous
ses flux.&lt;/p&gt;
&lt;p&gt;Vous pouvez utiliser Framanews sur des serveurs de &lt;a class="reference external" href="http://www.framasoft.net"&gt;Framasoft&lt;/a&gt; ou sur votre serveur. C'est ce que nous allons
faire ici.&lt;/p&gt;
&lt;div class="section" id="installer-les-bons-paquets"&gt;
&lt;h2&gt;Installer les bons paquets&lt;/h2&gt;
&lt;p&gt;Pour faire fonctionner framanews, nous avons besoin de :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;git&lt;/tt&gt; pour récupérer framanews et ses plugins ou ses thèmes.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;PostgreSQL&lt;/tt&gt; comme système de base de données.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;php&lt;/tt&gt; et de ses extensions pour fonctionner avec &lt;tt class="docutils literal"&gt;PostgreSQL&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;nginx&lt;/tt&gt; (serveur web)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sur un système basé sur debian, nous pouvons installer tous ça avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo apt-get install php5 php5-pgsql php5-fpm php-apc php5-curl php5-cli
sudo apt-get install git postgresql nginx
&lt;/pre&gt;
&lt;p&gt;Sur un système basé sur CentOS/RHEL :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
yum install postgresql postgresql-libs postgresql-server
yum install php-fpm php-gd php-mbstring php-pgsql php-pdo
yum install git nginx
&lt;/pre&gt;
&lt;p&gt;Reste à activer les bons services (nous les lancerons un peu plus tard) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
service nginx enable
service postgresql enable
service php-fpm enable
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="recuperer-framanews"&gt;
&lt;h2&gt;Récupérer framanews&lt;/h2&gt;
&lt;p&gt;Framanews est disponible sur github. Pour le récupérer, placez vous dans le
dossier où vous voulez le placer (&lt;tt class="docutils literal"&gt;/var/www/&lt;/tt&gt; pour moi) et lancez :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git clone https://github.com/framasoft/framanews_ttrss.git
&lt;/pre&gt;
&lt;p&gt;Framanews sera alors placé dans &lt;tt class="docutils literal"&gt;/var/www/framanews_ttrss&lt;/tt&gt; ce que je ne trouve
pas parlant. Je propose de renommer ce dossier en framanews avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
mv framanews_ttrss framanews
&lt;/pre&gt;
&lt;p&gt;Ensuite, nous devons donner les droits au serveur pour qu'il puisse faire son
travail correctement. La commande peut varier en fonction de votre système. Sous
debian et affiliée, l'utilisateur s'appelle &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt; et mais &lt;tt class="docutils literal"&gt;apache&lt;/tt&gt; sous
CentOS/RHEL et affiliée. On fera donc au choix :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
chown -R www-data:root framanews/
&lt;/pre&gt;
&lt;p&gt;ou :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
chown -R apache:root framanews/
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-nginx"&gt;
&lt;h2&gt;Configurer nginx&lt;/h2&gt;
&lt;p&gt;Rien de très compliqué. Copiez/collez simplement les lignes suivantes dans :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;/etc/nginx/conf.d/ttrss.conf&lt;/tt&gt; sur CentOS/RHEL&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;/etc/nginx/sites-available/ttrss.conf&lt;/span&gt;&lt;/tt&gt; sur Debian&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;VOTRE_SERVEUR&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# ttrss.jujens.eu pour moi
&lt;/span&gt;   &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="s"&gt;/var/www/framanews&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# Changer ce chemin au besoin
&lt;/span&gt;   &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;\.php$&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="s"&gt;unix:/var/run/php5-fpm.sock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;fastcgi_param&lt;/span&gt; &lt;span class="s"&gt;SCRIPT_FILENAME&lt;/span&gt; &lt;span class="nv"&gt;$document_root$fastcgi_script_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;fastcgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il ne reste plus qu'à lancer nginx et php-fpm :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
service nginx start
service php-fpm start
&lt;/pre&gt;
&lt;p&gt;Vous pourrez trouver des informations complémentaires utiles dans &lt;a class="reference external" href="http://wiki.jujens.eu/doku.php?id=server:nginx"&gt;mes notes sur
nginx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Avec cette configuration, &lt;strong&gt;le trafic (dont votre mot de passe) est en
clair&lt;/strong&gt;. Pour faire du https avec nginx et des certificats auto-signés, je vous
propose &lt;a class="reference external" href="/posts/2014/Jun/29/nginx-https/"&gt;ce post&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-la-base-de-donnees"&gt;
&lt;h2&gt;Configurer la base de données&lt;/h2&gt;
&lt;div class="section" id="autoriser-la-connexion"&gt;
&lt;h3&gt;Autoriser la connexion&lt;/h3&gt;
&lt;p&gt;PostgreSQL possède de &lt;a class="reference external" href="http://www.postgresql.org/docs/current/static/auth-methods.html"&gt;nombreux mécanismes d'authentification&lt;/a&gt;. Nous allons
vérifier que le mécanisme configuré est le bon. Pour cela :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Sous debian, éditez :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
/etc/postgresql/9.1/main/pg_hba.conf
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Sous CentOS, éditez :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
/var/lib/pgsql/data/pg_hba.conf
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je vous propose la configuration suivante :&lt;/p&gt;
&lt;pre class="code kconfig literal-block"&gt;
&lt;span class="c1"&gt;# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
# &amp;quot;local&amp;quot; is for Unix domain socket connections only
&lt;/span&gt;local        all         all                               ident
&lt;span class="c1"&gt;# Allow auth with password
#local       all         all                               password
&lt;/span&gt;host         all         all         &lt;span class="mi"&gt;127&lt;/span&gt;.0.0.1/32          password
host         all         all         ::1/128               password
&lt;/pre&gt;
&lt;p&gt;Elle autorise :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;La connexion par socket local&lt;/li&gt;
&lt;li&gt;La connexion à toutes les bases de données pour tous les utilisateurs
(utilisateurs de la base de données, pas les utilisateurs du système) sur les
adresses 127.0.0.1/32 avec mot de passe.&lt;/li&gt;
&lt;li&gt;Idem pour les adresses ipv6&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="creer-la-base-de-donnees"&gt;
&lt;h3&gt;Créer la base de données&lt;/h3&gt;
&lt;p&gt;Nous allons maintenant créer la base de données et son utilisateur à l'aide des
commandes ci-dessous (gardez le nom de la base de données, le nom de
l'utilisateur et son mot de passe, nous allons en avoir besoin dans pas longtemps).&lt;/p&gt;
&lt;pre class="literal-block"&gt;
root&amp;#64;jujens:/home/jenselme# su - -c &amp;quot;psql&amp;quot; postgres
psql (9.1.13)
Saisissez « help » pour l'aide.

postgres=# DROP USER ttrss;
DROP ROLE
postgres=# CREATE USER ttrss WITH PASSWORD 'SUPER_MDP';
CREATE ROLE
postgres=# CREATE DATABASE ttrss OWNER ttrss ENCODING 'UTF8';
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON DATABASE ttrss TO ttrss;
GRANT
&lt;/pre&gt;
&lt;p&gt;Reste à lancer PostgreSQL :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
service postgresql start
&lt;/pre&gt;
&lt;p&gt;Pour sauvegarder, je vous invite à lire &lt;a class="reference external" href="/posts/2014/Jun/29/sauvegarder-base-donnees-postgresql/"&gt;cet article&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="finaliser-l-installation"&gt;
&lt;h2&gt;Finaliser l'installation&lt;/h2&gt;
&lt;p&gt;Allez sur l'adresse que vous avez choisie pour Framanews (ttrss.jujens.eu pour
moi). Il reste à remplir avec les informations demandées (à adapter à votre cas) :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Type de base de données : PostgreSQL&lt;/li&gt;
&lt;li&gt;Username : ttrss&lt;/li&gt;
&lt;li&gt;Password : SUPER_MDP&lt;/li&gt;
&lt;li&gt;Database name : ttrss&lt;/li&gt;
&lt;li&gt;Port : 5432&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Remplir les infos de base de données" src="/images/installer-framanews/ttrss-1.png" style="width: 600px;" /&gt;
&lt;p&gt;On teste la configuration :&lt;/p&gt;
&lt;img alt="Tester la configuration" src="/images/installer-framanews/ttrss-2.png" style="width: 600px;" /&gt;
&lt;p&gt;Et on sauvegarde le fichier de conf :&lt;/p&gt;
&lt;img alt="Fichier de conf" src="/images/installer-framanews/ttrss-3.png" style="width: 600px;" /&gt;
&lt;p&gt;Et voilà !&lt;/p&gt;
&lt;img alt="Framanews" src="/images/installer-framanews/ttrss-4.png" style="width: 600px;" /&gt;
&lt;p&gt;Je vous laisse faire un tour dans les options pour adapter Framanews à vos
besoins.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="mise-a-jour-des-flux"&gt;
&lt;h2&gt;Mise à jour des flux&lt;/h2&gt;
&lt;p&gt;Par défaut, les flux ne se mettent pas à jour via l'interface web. La solution
recommandée est d'entrer la ligne suivante dans un terminal :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
su www-data -c './update.php --daemon&amp;amp; &amp;gt; /dev/null&amp;amp;'
&lt;/pre&gt;
&lt;p&gt;Malheureusement, dès que vous quitterez le terminal, le programme sortira. Je
propose donc plutôt d'utiliser &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/Crontab#Syntaxe_de_la_table"&gt;le crontab&lt;/a&gt;. Pour éditer le
crontab, tapez (en tant que root) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
crontab -e
&lt;/pre&gt;
&lt;p&gt;et ajouter la ligne suivante pour une mise à jour toutes les 30 minutes (le
chemin est à adapter) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
*/30 * * * * su www-data -c '/usr/bin/php    /var/www/framanews/update.php --feeds --quiet'
&lt;/pre&gt;
&lt;p&gt;Pour information : cette ligne lance en tant que l'utilisateur &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;www-data&lt;/span&gt;&lt;/tt&gt; le
script update.php.&lt;/p&gt;
&lt;p&gt;Si vous n'avez pas de crontab, vous pouvez utiliser la mise à jour en arrière
plan. Framanews va alors tenter de mettre à jour les flux tant qu'il est ouvert
dans votre navigateur. Pour cela, dans &lt;tt class="docutils literal"&gt;/var/www/framanews/config.php&lt;/tt&gt; mettre
&lt;tt class="docutils literal"&gt;SIMPLE_UPDATE_MODE&lt;/tt&gt; à &lt;tt class="docutils literal"&gt;TRUE&lt;/tt&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="plugins-et-themes"&gt;
&lt;h2&gt;Plugins et thèmes&lt;/h2&gt;
&lt;p&gt;ttrss (et donc Framanews) peut être étendu grâce à des plugins et son pas très
joli thème de base peut être changé. La liste des plugins est disponible &lt;a class="reference external" href="http://tt-rss.org/redmine/projects/tt-rss/wiki/Plugins"&gt;ici&lt;/a&gt; et celle des thèmes
&lt;a class="reference external" href="http://tt-rss.org/redmine/projects/tt-rss/wiki/Themes"&gt;là&lt;/a&gt;. Installer un
thème ou un plugin n'est pas compliqué.&lt;/p&gt;
&lt;div class="section" id="plugins"&gt;
&lt;h3&gt;Plugins&lt;/h3&gt;
&lt;p&gt;Par exemple, pour le plugin framarticle_toolbar, il suffit de :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;Se placer dans le dossier &lt;em&gt;plugin&lt;/em&gt; de votre installation de Framanews
(/var/www/framanews/plugin pour moi.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;Lancer :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
git clone https://github.com/framasoft/framarticle_toolbar.git
chown -R www-data:root framarticle_toolbar/
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On l'active dans &lt;em&gt;Actions &amp;gt; Préférences &amp;gt; Préférences &amp;gt; Plugin&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="theme"&gt;
&lt;h3&gt;Thème&lt;/h3&gt;
&lt;p&gt;On procède comme pour un plugin, mais en se plaçant dans le dossier theme. On
active le thème dans &lt;em&gt;Actions &amp;gt; Préférences&lt;/em&gt; directement dans l'onglet préférence.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="sources"&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Le site officiel de framanews : &lt;a class="reference external" href="https://framanews.org/install.php"&gt;https://framanews.org/install.php&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le site officiel de Tiny Tiny RSS : &lt;a class="reference external" href="http://tt-rss.org"&gt;http://tt-rss.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How To Install TTRSS with Nginx for Debian 7 on a VPS :
&lt;a class="reference external" href="https://www.digitalocean.com/community/tutorials/how-to-install-ttrss-with-nginx-for-debian-7-on-a-vps"&gt;https://www.digitalocean.com/community/tutorials/how-to-install-ttrss-with-nginx-for-debian-7-on-a-vps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tiny Tiny RSS on CentOS with nginx and MYSQL :
&lt;a class="reference external" href="https://www.zufallsheld.de/2013/11/03/tiny-tiny-rss-centos-nginx-mysql/"&gt;https://www.zufallsheld.de/2013/11/03/tiny-tiny-rss-centos-nginx-mysql/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Changing the tt-rss database from MySQL to Postgresql :
&lt;a class="reference external" href="https://www.zufallsheld.de/2014/02/25/changing-the-tt-rss-database-from-mysql-to-postgresql/"&gt;https://www.zufallsheld.de/2014/02/25/changing-the-tt-rss-database-from-mysql-to-postgresql/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Auto-hébergement"></category><category term="framanews"></category><category term="tt-rss"></category><category term="nginx"></category><category term="PostgreSQL"></category></entry><entry><title>Utiliser isso pour avoir des commentaires auto-hébergés</title><link href="//www.jujens.eu/posts/2014/Jun/08/commentaires-isso/" rel="alternate"></link><published>2014-06-08T00:00:00+02:00</published><updated>2014-06-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-06-08:/posts/2014/Jun/08/commentaires-isso/</id><summary type="html">&lt;p&gt;Lorsque j'ai lancé ce blog, j'utilisais &lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/pelican_comment_system"&gt;un plugin de pelican&lt;/a&gt; pour avoir un système de commentaires statiques. Je ne suis en effet pas un grand fan des commentaires hébergés chez des prestataires externes comme disqus pour des questions de vie privée. Ce plugin me semblait un bon compromis : il ajoute …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Lorsque j'ai lancé ce blog, j'utilisais &lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/pelican_comment_system"&gt;un plugin de pelican&lt;/a&gt; pour avoir un système de commentaires statiques. Je ne suis en effet pas un grand fan des commentaires hébergés chez des prestataires externes comme disqus pour des questions de vie privée. Ce plugin me semblait un bon compromis : il ajoute un formulaire grâce à du javascript dans lequel on peut entrer son commentaire qui est ensuite envoyé par mail à l'administrateur du site. Celui-ci doit ensuite copier/coller le contenu du commentaire dans un fichier dédié.&lt;/p&gt;

&lt;p&gt;Cela présente l'avantage d'être simple et respectueux de la vie privée bien qu'un peu fastidieux pour l'administrateur. Mais quand on a pas beaucoup de commentaire, ce n'est pas très grave et ça permet de les modérer.&lt;/p&gt;

&lt;p&gt;Je me disais que c'était très bien et puis récemment, je suis tombé sur &lt;a href="http://hackriculture.fr/isso-commentaires-auto-heberges-pour-pelican-et-autres-sites-statiques.html"&gt;cet article&lt;/a&gt; qui présente issos. Isso est un petit logiciel qui vous permet de stocker les commentaires dans une base de données sqlite et de les enregistrer/afficher grâce à un peu de javascript. Cela vous permet de combiner les avantages de l'auto-hébergement et de l'aspect dynamique d'un service comme disqus. Petit plus sympa, isso peut vous envoyer un mail à chaque commentaire ajouté avec la possibilité de les modérer.&lt;/p&gt;

&lt;p&gt;C'est simple, efficace et d'après mes tests ça marche plutôt bien. Évidement, ce n'est pas utilisable si vous avez vraiment beaucoup de commentaires, ça reste du sqlite ;-). Il manque également une vraie interface d'administration pour gérer les commentaires.&lt;/p&gt;

&lt;p&gt;Voilà un exemple basique de configuration.&lt;/p&gt;

&lt;div class="pygments"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[general]&lt;/span&gt;

&lt;span class="c1"&gt;# File location to the SQLite3 database, highly recommended&lt;/span&gt;
&lt;span class="c1"&gt;# to change this location to a non-temporary location!&lt;/span&gt;
&lt;span class="na"&gt;dbpath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/var/lib/isso/comments.db&lt;/span&gt;

&lt;span class="c1"&gt;# URL to your website. When you start Isso, it will probe&lt;/span&gt;
&lt;span class="c1"&gt;# your website with a simple GET / request to see if it can&lt;/span&gt;
&lt;span class="c1"&gt;# reach the webserver. If this fails, Isso may not be able&lt;/span&gt;
&lt;span class="c1"&gt;# check if a web page exists, thus fails to accept new&lt;/span&gt;
&lt;span class="c1"&gt;# comments.&lt;/span&gt;
&lt;span class="c1"&gt;# You can supply more than one host.&lt;/span&gt;
&lt;span class="na"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;http://www.jujens.eu&lt;/span&gt;

&lt;span class="na"&gt;notify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;smtp&lt;/span&gt;

&lt;span class="k"&gt;[server]&lt;/span&gt;
&lt;span class="na"&gt;listen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8080/&lt;/span&gt;

&lt;span class="k"&gt;[moderation]&lt;/span&gt;

&lt;span class="c1"&gt;# Enable comment moderation queue. This option only affects&lt;/span&gt;
&lt;span class="c1"&gt;# new comments. Comments in modertion queue are not visible&lt;/span&gt;
&lt;span class="c1"&gt;# to other users until you activate them.&lt;/span&gt;
&lt;span class="na"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;false&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Pour lancer isso en arrière plan avec sa configuration :&lt;/p&gt;

&lt;div class="pygments"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;/usr/local/bin/isso -c /etc/isso.conf run &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1&gt;Pour en savoir plus&lt;/h1&gt;

&lt;p&gt;** L'article cité plus haut : &lt;a href="http://hackriculture.fr/isso-commentaires-auto-heberges-pour-pelican-et-autres-sites-statiques.html"&gt;http://hackriculture.fr/isso-commentaires-auto-heberges-pour-pelican-et-autres-sites-statiques.html&lt;/a&gt;&lt;br /&gt;
** Le site officiel d'isso : &lt;a href="http://posativ.org/isso/"&gt;http://posativ.org/isso/&lt;/a&gt;&lt;/p&gt;</content><category term="Blog"></category><category term="pelican"></category><category term="python"></category></entry><entry><title>Markdown vs creole vs Restructured Text vs org-mode</title><link href="//www.jujens.eu/posts/2014/May/10/langages-balisage/" rel="alternate"></link><published>2014-05-10T00:00:00+02:00</published><updated>2014-05-10T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-05-10:/posts/2014/May/10/langages-balisage/</id><summary type="html">&lt;p&gt;Comme je l'ai déjà détaillé &lt;a href="/posts/2013/Aug/23/de-latex-a-orgmode/"&gt;ici&lt;/a&gt;, je ne suis pas un grand fan des syntaxes verbeuses à la LaTeX ou HTML et je préfère les langages à balisages légers (et oui, je ne suis pas non plus fan des WYSIWYG). Comme j'ai eu l'occasion d'en tester plusieurs ces derniers temps …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Comme je l'ai déjà détaillé &lt;a href="/posts/2013/Aug/23/de-latex-a-orgmode/"&gt;ici&lt;/a&gt;, je ne suis pas un grand fan des syntaxes verbeuses à la LaTeX ou HTML et je préfère les langages à balisages légers (et oui, je ne suis pas non plus fan des WYSIWYG). Comme j'ai eu l'occasion d'en tester plusieurs ces derniers temps, je vous propose une petite comparaison.&lt;/p&gt;

&lt;h1&gt;Markdown&lt;/h1&gt;

&lt;p&gt;Peut être le plus connus et le plus utilisé. On le retrouve sur &lt;a href="http://github.com"&gt;Github&lt;/a&gt;, &lt;a href="http://stackoverflow.com"&gt;Stackoverflow&lt;/a&gt;, &lt;a href="http://getpelican.com"&gt;pelican&lt;/a&gt; et dans les commentaires de ce blog :D. La syntaxe est simple ce qui doit expliquer sa popularité.&lt;/p&gt;

&lt;p&gt;Malheureusement, le markdown de base n'est pas très complet. Il ne gère pas les tableaux par exemple. Certes, on peut insérer du HTML dans du code markdown pour palier ce problème mais bon, le but c'est justement de pouvoir utiliser quelque chose de plus léger que le HTML. Cela a donc assez logiquement entraîné la création de diverses extensions comme &lt;a href="http://github.github.com/github-flavored-markdown/"&gt;le markdow à la sauce github&lt;/a&gt; qui ne sont évidement pas toujours compatibles entre elle.&lt;/p&gt;

&lt;p&gt;Ce langage contient aussi un point que je trouve particulièrement mal fait : pour insérer un saut de ligne, on peut ajouter deux espaces à la fin de la dite ligne. Pour moi c'est très mauvais : on ne voit pas si on a modifié ces espaces et tous mes éditeurs de texte sont paramétrés pour enlever les espaces de fin de ligne.&lt;/p&gt;

&lt;p&gt;Mais ce qui m'a fait fuir ce langage c'est la possibilité d'ajouter du code que je trouve vraiment pourrie. On peut ajouter du code, soit en l'entourant avec &lt;tt&gt; ~~~ &lt;/tt&gt; soit en ajoutant deux tabulations devant. J'avais déjà testé la syntaxe avec les tildes et ça marchait plutôt bien. Puis en voulant ajouter du code sur ce blog j'ai eu des problèmes pour activer la coloration syntaxique si l'extension table des matières est active. La syntaxe avec les tildes ne fonctionnait plus et j'ai bien galéré avec l'autre. Du coup, j'ai regardé d'autres syntaxes.&lt;/p&gt;

&lt;h1&gt;Restructured Text&lt;/h1&gt;

&lt;p&gt;L'autre syntaxe bien supportée par Pelican est le &lt;a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html"&gt;Restructured Text&lt;/a&gt; (rst en abrégé). C'est beaucoup plus complet que markdown et ça supporte beaucoup de chose : ajouter des propriétés aux images insérées, les références, sommaire et index… Il faut dire que le langage a été conçu pour remplacer LaTeX pour la documentation de python. Donc, mécaniquement, il faut pas mal d'options. Et je dois dire que le résultat, du point de vue des fonctionnalités offertes en est un concurrent sérieux pour l'export en html. LaTeX garde l'avantage pour l'export pdf car c'est aussi un système de mise en page très pointu (ce dont on a pas forcément besoin pour autre chose que la page de garde cela dit).&lt;/p&gt;

&lt;p&gt;Pour être franc, mes premiers tests avec rst n'ont pas été concluant du tout. Premièrement, le fait qu'il soit nécessaire de souligner ces titres avec =, -, ou + suivant le niveau ne me plaît pas particulièrement, je trouve ça un peu lourd. Ici c'est d'autant plus lourd que le soulignement doit faire exactement la taille du titre, sinon rst génère une erreur.&lt;/p&gt;

&lt;p&gt;Ensuite, les sous-listes doivent être séparées de la liste parente par un saut de ligne et la puce doit être indentée précisément sous le premier caractère du texte de la liste parente. Le calvaire des indentations en python mais en pire !&lt;/p&gt;

&lt;p&gt;Enfin, les tableaux doivent être fait intégralement à la main.&lt;/p&gt;

&lt;p&gt;Et puis j'ai trouvé &lt;a href="http://www.inec.us/blog/2013/01/26/restructuredtext-markup-you-should-know-about/"&gt;cet article (en)&lt;/a&gt; qui m'a réconcilié avec le format. J'utilise désormais le &lt;a href="http://docutils.sourceforge.net/docs/user/emacs.html"&gt;rst-mode&lt;/a&gt; pour emacs qui permet de placer le bon nombre de caractères sous les titres avec &lt;tt&gt; ^u = &lt;/tt&gt;, fait l'indentation tout seul. J'ai aussi appris que emacs est capable sans plugin supplémentaire de créer des tableaux ascii compatible avec rst. J'ai donc retenté l'expérience et ce fut concluant. Maintenant, j'admets, j'aime bien et j'ai pris plaisir à écrire &lt;a href="/posts/2014/May/05/Communication-serie/"&gt;mon tuto sur la communication série en arduino&lt;/a&gt; avec. Par contre, compte tenu de sa relative verbosité, je le réserve pour les longs articles ou les tutos.&lt;/p&gt;

&lt;h1&gt;Creole&lt;/h1&gt;

&lt;p&gt;Encore un autre langage à balise. Il a été créé dans le but d'unifier les langages existants. Il est léger et plutôt complet. Voir par &lt;a href="http://www.wikicreole.org/wiki/Creole1.0"&gt;là&lt;/a&gt; pour la syntaxe. J'admets avoir été séduit par ce langage simple et efficace. J'ai même fait &lt;a href="https://github.com/getpelican/pelican-plugins/tree/master/creole_reader"&gt;le plugin pelican&lt;/a&gt; pour l'utiliser. Je l'utilise pour les articles de blog assez courts qui n'ont pas besoin de la puissance de rst.&lt;/p&gt;

&lt;h1&gt;Org-mode&lt;/h1&gt;

&lt;p&gt;Je n'ai pas grand chose de plus à dire par rapport à mon dernier article : &lt;a href="/posts/2013/Aug/23/de-latex-a-orgmode/"&gt;de LaTeX à org-mode&lt;/a&gt;. C'est complet et bien intégré avec emacs. Si je m'en suis un peu détourné c'est à cause du manque d'implémentation dans pelican. Il faut impérativement passer par emacs et on perd la possibilité d'utiliser le système de cache de pelican.&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Le moins que l'on puisse dire c'est qu'on a énormément de choix. Je suis personnellement très déçu par mardown et j'ai du mal à comprendre pourquoi il est si populaire alors que d'autres langages comme creole sont vraiment bien.&lt;/p&gt;

&lt;p&gt;Je pense également utiliser rst pour mes prochains rapport plutôt que LaTeX ou org-mode. Je trouve ce format mieux fait que org-mode bien qu'un peu plus verbeux. Mais je vais certainement continuer à utiliser org-mode pour mes notes.&lt;/p&gt;</content><category term="Blog"></category><category term="markup"></category><category term="Markdown"></category><category term="Creole"></category><category term="Rst"></category><category term="org-mode"></category><category term="emacs"></category></entry><entry><title>Ajouter un dépôt git distant</title><link href="//www.jujens.eu/posts/2014/May/09/git-ajouter-depot-distant/" rel="alternate"></link><published>2014-05-09T00:00:00+02:00</published><updated>2014-05-09T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-05-09:/posts/2014/May/09/git-ajouter-depot-distant/</id><summary type="html">&lt;p class="first last"&gt;git est tout à fait capable de gérer plusieurs dépôt distant. Voilà
comment en ajouter un.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Un cas d'utilisation typique est lorsque vous avez forké un dépôt sur github et
que vous voulez le synchroniser avec le dépôt initial. Commençons par lister les
sources disponibles et ajouter la nouvelle source avec la commande &lt;tt class="docutils literal"&gt;git remote
add NOM URL&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
&lt;span class="o"&gt;[&lt;/span&gt;jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git remote -v
origin        git&amp;#64;github.com:Jenselme/SimpleCV.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin        git&amp;#64;github.com:Jenselme/SimpleCV.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git remote add upstream https://github.com/sightmachine/SimpleCV.git

&lt;span class="o"&gt;[&lt;/span&gt;jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git remote -v          &lt;span class="o"&gt;[&lt;/span&gt;git&lt;span class="o"&gt;][&lt;/span&gt;SimpleCV/.&lt;span class="o"&gt;][&lt;/span&gt;develop&lt;span class="o"&gt;]&lt;/span&gt;
origin        https://github.com/Jenselme/SimpleCV.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin        https://github.com/Jenselme/SimpleCV.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
upstream      https://github.com/sightmachine/SimpleCV.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
upstream      https://github.com/sightmachine/SimpleCV.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il ne reste plus qu'à mettre à jour le dépôt.&lt;/p&gt;
&lt;div class="section" id="fetch"&gt;
&lt;h2&gt;fetch&lt;/h2&gt;
&lt;pre class="code sh literal-block"&gt;
jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git fetch upstream
remote: Counting objects: &lt;span class="m"&gt;155&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
remote: Compressing objects: &lt;span class="m"&gt;100&lt;/span&gt;% &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;72&lt;/span&gt;/72&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
remote: Total &lt;span class="m"&gt;155&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta &lt;span class="m"&gt;102&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;, reused &lt;span class="m"&gt;130&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta &lt;span class="m"&gt;83&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
Receiving objects: &lt;span class="m"&gt;100&lt;/span&gt;% &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;155&lt;/span&gt;/155&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="m"&gt;208&lt;/span&gt;.82 KiB &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;237&lt;/span&gt;.00 KiB/s, &lt;span class="k"&gt;done&lt;/span&gt;.
Resolving deltas: &lt;span class="m"&gt;100&lt;/span&gt;% &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;102&lt;/span&gt;/102&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
From https://github.com/sightmachine/SimpleCV
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      AVT-timing -&amp;gt; upstream/AVT-timing
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      SCV-1      -&amp;gt; upstream/SCV-1
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      develop    -&amp;gt; upstream/develop
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      gsoc       -&amp;gt; upstream/gsoc
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      master     -&amp;gt; upstream/master
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      njotask/JNAPC-502 -&amp;gt; upstream/njotask/JNAPC-502
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      task/DEMOS-65 -&amp;gt; upstream/task/DEMOS-65
* &lt;span class="o"&gt;[&lt;/span&gt;new branch&lt;span class="o"&gt;]&lt;/span&gt;      task/JNAPC-520 -&amp;gt; upstream/task/JNAPC-520
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="merge"&gt;
&lt;h2&gt;merge&lt;/h2&gt;
&lt;pre class="code sh literal-block"&gt;
&lt;span class="o"&gt;[&lt;/span&gt;jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git branch         &lt;span class="o"&gt;[&lt;/span&gt;git&lt;span class="o"&gt;][&lt;/span&gt;SimpleCV/.&lt;span class="o"&gt;][&lt;/span&gt;develop&lt;span class="o"&gt;]&lt;/span&gt;
* develop

&lt;span class="o"&gt;[&lt;/span&gt;jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git checkout develop

&lt;span class="o"&gt;[&lt;/span&gt;jenselme&amp;#64;fastolfe SimpleCV&lt;span class="o"&gt;]&lt;/span&gt;% git merge upstream/develop
Merge made by the &lt;span class="s1"&gt;'recursive'&lt;/span&gt; strategy.
README.markdown        &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt; +++++++++++++++++++++++++-------
SimpleCV/ImageClass.py &lt;span class="p"&gt;|&lt;/span&gt;  &lt;span class="m"&gt;2&lt;/span&gt; +-
&lt;span class="m"&gt;2&lt;/span&gt; files changed, &lt;span class="m"&gt;26&lt;/span&gt; insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="m"&gt;8&lt;/span&gt; deletions&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Source : &lt;a class="reference external" href="https://help.github.com/articles/syncing-a-fork"&gt;https://help.github.com/articles/syncing-a-fork&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="git"></category></entry><entry><title>Une petite sélection de jeu libre pour se détendre</title><link href="//www.jujens.eu/posts/2014/May/07/selection-jeux-libres/" rel="alternate"></link><published>2014-05-07T00:00:00+02:00</published><updated>2014-05-07T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-05-07:/posts/2014/May/07/selection-jeux-libres/</id><summary type="html">&lt;p&gt;Durant les dernières vacances, j'ai voulu me détendre avec quelques jeux&lt;br /&gt;
libres. J'en ai retenu 3 qui sont simples et distrayants. J'ai donc exclu &lt;a href="http://play0ad.com/"&gt;0ad&lt;/a&gt; et&lt;br /&gt;
&lt;a href="http://www.wesnoth.org/"&gt;Battle for Wesnoth&lt;/a&gt; qui sont des jeux de stratégie un peu trop « prise&lt;br /&gt;
de tête », pas assez simples (mais très bons quand même).&lt;/p&gt;

&lt;h1&gt;SuperTuxKart …&lt;/h1&gt;</summary><content type="html">&lt;p&gt;Durant les dernières vacances, j'ai voulu me détendre avec quelques jeux&lt;br /&gt;
libres. J'en ai retenu 3 qui sont simples et distrayants. J'ai donc exclu &lt;a href="http://play0ad.com/"&gt;0ad&lt;/a&gt; et&lt;br /&gt;
&lt;a href="http://www.wesnoth.org/"&gt;Battle for Wesnoth&lt;/a&gt; qui sont des jeux de stratégie un peu trop « prise&lt;br /&gt;
de tête », pas assez simples (mais très bons quand même).&lt;/p&gt;

&lt;h1&gt;SuperTuxKart&lt;/h1&gt;

&lt;p&gt;C'est un jeu de course qui ressemble au célèbre Mario Kart. On y joue seul ou à&lt;br /&gt;
plusieurs (pas pu tester faute de manette). On a le choix entre plusieurs karts&lt;br /&gt;
qui s'inspirent tous d'un projet libre. On retrouve donc Tux, Beastie,&lt;br /&gt;
ElePHPant, … Le jeu dispose d'un mode histoire : le but étant de gagner les&lt;br /&gt;
courses proposées pour libérer GNU. Le scénario n'est donc pas très profond,&lt;br /&gt;
mais ce n'est pas ce qu'on lui demande.&lt;/p&gt;

&lt;p&gt;Le jeu contient tous les éléments qui font qu'un jeu de course comme ça est bien&lt;br /&gt;
: nitro, trucs à lancer sur les adversaires (ballon de basket, cake explosif,…),&lt;br /&gt;
plutôt bons graphismes et de bonnes musiques qui s'accordent bien avec la course.&lt;/p&gt;

&lt;h2&gt;Captures&lt;/h2&gt;

&lt;p&gt;&lt;img src="/images/selection-jeux-libres/SuperTuxKart-00.resized.png" title="STK 1" alt="STK 1" /&gt;&lt;br /&gt;
&lt;img src="/images/selection-jeux-libres/SuperTuxKart-01.resized.png" title="STK 2" alt="STK 2" /&gt;&lt;br /&gt;
&lt;img src="/images/selection-jeux-libres/SuperTuxKart-02.resized.png" title="STK 3" alt="STK 3" /&gt;&lt;/p&gt;

&lt;h2&gt;Liens et téléchargements&lt;/h2&gt;

&lt;ul&gt;
	&lt;li&gt;Site officiel : &lt;a href="http://supertuxkart.sourceforge.net/"&gt;http://supertuxkart.sourceforge.net/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Téléchargement (Disponible dans les dépôts de la plupart des distributions) : &lt;a href="http://supertuxkart.sourceforge.net/Downloads"&gt;http://supertuxkart.sourceforge.net/Downloads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Funguloïds&lt;/h1&gt;

&lt;p&gt;C'est un jeu assez étrange. Vous êtes une sorte de comète et vous devez&lt;br /&gt;
collecter des champignons de couleur pour les ramener sur leur platforme tout en&lt;br /&gt;
évitant des astéroïdes. Vous gagnez alors des points et changer de carte. Cela&lt;br /&gt;
étant dit, le jeu est vraiment très beau graphiquement et sa musique calme vous&lt;br /&gt;
permettra de vous reposer tout en vous amusant.&lt;/p&gt;

&lt;h2&gt;Captures&lt;/h2&gt;

&lt;p&gt;&lt;img src="/images/selection-jeux-libres/Funguloids-00.resized.png" title="Funguloïds 1" alt="Funguloïds 1" /&gt;&lt;br /&gt;
&lt;img src="/images/selection-jeux-libres/Funguloids-01.resized.png" title="Funguloïds 2" alt="Funguloïds 2" /&gt;&lt;br /&gt;
&lt;img src="/images/selection-jeux-libres/Funguloids-02.resized.png" title="Funguloïds 3" alt="Funguloïds 3" /&gt;&lt;/p&gt;

&lt;h2&gt;Liens et téléchargements&lt;/h2&gt;

&lt;ul&gt;
	&lt;li&gt;Site officiel : &lt;a href="http://funguloids.sourceforge.net/"&gt;http://funguloids.sourceforge.net/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Téléchargement (Disponible dans les dépôts de la plupart des distributions) : &lt;a href="http://funguloids.sourceforge.net/download.html"&gt;http://funguloids.sourceforge.net/download.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;SuperTux 2&lt;/h1&gt;

&lt;p&gt;Pour faire simple : c'est Tux qui se prend pour Mario sur la banquise. C'est un&lt;br /&gt;
bon jeu de platforme, simple mais efficace.&lt;/p&gt;

&lt;h2&gt;Captures&lt;/h2&gt;

&lt;p&gt;&lt;img src="/images/selection-jeux-libres/SuperTux-00.resized.png" title="SuperTux 1" alt="SuperTux 1" /&gt;&lt;br /&gt;
&lt;img src="/images/selection-jeux-libres/SuperTux-01.resized.png" title="SuperTux 2" alt="SuperTux 2" /&gt;&lt;br /&gt;
&lt;img src="/images/selection-jeux-libres/SuperTux-02.resized.png" title="SuperTux 3" alt="SuperTux 3" /&gt;&lt;/p&gt;

&lt;h2&gt;Liens et téléchargements&lt;/h2&gt;

&lt;ul&gt;
	&lt;li&gt;Site officiel : &lt;a href="http://supertux.lethargik.org/"&gt;http://supertux.lethargik.org/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Téléchargement (Disponible dans les dépôts de la plupart des distributions) : &lt;a href="http://supertux.lethargik.org/download.html"&gt;http://supertux.lethargik.org/download.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Blog"></category><category term="jeux"></category><category term="libre"></category></entry><entry><title>La communication série avec arduino</title><link href="//www.jujens.eu/posts/2014/May/05/Communication-serie/" rel="alternate"></link><published>2014-05-05T00:00:00+02:00</published><updated>2014-05-05T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-05-05:/posts/2014/May/05/Communication-serie/</id><summary type="html">&lt;p&gt;La communication série est indispensable pour dialoguer avec votre Arduino
puisque c'est le mode de transmission utilisé pour communiquer avec la
carte. Dans ce tuto je vais vous expliquer comment ça fonctionne avec des
exemples pratiques pour faire communiquer une carte arduino (le modèle n'importe
pas) et votre PC grâce …&lt;/p&gt;</summary><content type="html">&lt;p&gt;La communication série est indispensable pour dialoguer avec votre Arduino
puisque c'est le mode de transmission utilisé pour communiquer avec la
carte. Dans ce tuto je vais vous expliquer comment ça fonctionne avec des
exemples pratiques pour faire communiquer une carte arduino (le modèle n'importe
pas) et votre PC grâce à une connexion USB. Nous utiliserons dans un premier
temps l'IDE Arduino puis du code Python. Je suppose que vous avez quelques bases
en programmation. Les exemples seront suffisamment simples pour que la
connaissance préalable de python ne soit pas nécessaire.&lt;/p&gt;
&lt;p&gt;Le tuto peut se réaliser indifféremment sous Windows, GNU/Linux, Mac ou
autre. Néanmoins, les exemples fonctionnent tel quel uniquement sous linux. Sous
d'autres systèmes, vous pouvez être amené à changer les chemins des ports. Le
reste devrait rester inchangé.&lt;/p&gt;
&lt;p&gt;Tous les codes sont disponibles en &lt;a class="reference internal" href="#telechargement"&gt;téléchargement&lt;/a&gt; à la fin de ce document sous
licence &lt;a class="reference external" href="http://www.apache.org/licenses/LICENSE-2.0.html"&gt;Apache v2&lt;/a&gt;.&lt;/p&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;&lt;strong&gt;Sommaire&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#presentation" id="id2"&gt;Présentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#pre-requis" id="id3"&gt;Pré-requis&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#logiciels-et-bibliotheques-a-installer" id="id4"&gt;Logiciels et bibliothèques à installer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#vocabulaire" id="id5"&gt;Vocabulaire&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#communiquer-avec-le-moniteur-serie" id="id6"&gt;Communiquer avec le moniteur série&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#communication-la-plus-simple-possible" id="id7"&gt;Communication la plus simple possible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#echo" id="id8"&gt;Echo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#lire-des-entiers" id="id9"&gt;Lire des entiers&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#lecture-basique-d-un-entier" id="id10"&gt;Lecture basique d'un entier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#faire-des-maths-avec-deux-entiers" id="id11"&gt;Faire des maths avec deux entiers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#communication-entre-un-programme-et-la-carte" id="id12"&gt;Communication entre un programme et la carte&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#lecture" id="id13"&gt;Lecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#ecriture" id="id14"&gt;Écriture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#influence-du-nombre-de-bauds" id="id15"&gt;Influence du nombre de bauds&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#conclusion" id="id16"&gt;Conclusion&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#en-resume" id="id17"&gt;En résumé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#quelques-problemes-frequents" id="id18"&gt;Quelques problèmes fréquents&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#probleme-de-telechargement" id="id19"&gt;Problème de téléchargement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#lecture-de-donnees-de-taille-indeterminees" id="id20"&gt;Lecture de données de taille indéterminées&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#telechargements" id="id21"&gt;Téléchargements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="presentation"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id2"&gt;Présentation&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;En communication série, on découpe l'information à transmettre en petits blocs
de taille fixe avant de la transmettre. La taille des blocs correspond au nombre
des lignes disponibles pour la transmission des données.&lt;/p&gt;
&lt;p&gt;Ce type de communication s'oppose à la communication parallèle. En communication
parallèle, il y a une ligne par bits à transmettre. Tous les bits sont donc
transmis en même temps. Pour une même fréquence de communication, la
communication parallèle est donc plus rapide.&lt;/p&gt;
&lt;p&gt;L'avantage de la communication série sur la communication parallèle est qu'elle
nécessite moins de lignes, donc moins de broches, donc moins de composants. Son
coût est donc plus faible.&lt;/p&gt;
&lt;p&gt;Les protocoles de communication série les plus connus sont :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Le protocole &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/Universal_Serial_Bus"&gt;USB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le protocole &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/I2C"&gt;I2C&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Le protocole &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/PCI_Express"&gt;PCI Express&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="pre-requis"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id3"&gt;Pré-requis&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="logiciels-et-bibliotheques-a-installer"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id4"&gt;Logiciels et bibliothèques à installer&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Arduino IDE : l'IDE officiel arduino. Le moyen le plus simple d'écrire et de
télécharger les programmes sur la carte. Il est disponible sur le site
officiel d'Arduino : &lt;a class="reference external" href="http://arduino.cc/en/Main/Software#toc1"&gt;http://arduino.cc/en/Main/Software#toc1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python3 : indispensable pour exécuter les certains programmes d'exemple
(uniquement pour la partie &lt;a class="reference internal" href="#communication-entre-un-programme-et-la-carte"&gt;communication entre un programme et la
carte&lt;/a&gt;). Il se trouve dans les dépôts de votre distribution linux ou par là :
&lt;a class="reference external" href="http://www.python.org/"&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pyserial : c'est la bibliothèque python qui permet de faire de la
communication série. Elle est normalement dans les dépôts de votre
distribution linux. Elle peut aussi être installée via &lt;a class="reference external" href="https://pypi.python.org/pypi/pyserial/2.7"&gt;pip&lt;/a&gt; : &lt;tt class="docutils literal"&gt;pip install pyserial&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="vocabulaire"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id5"&gt;Vocabulaire&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Commençons par définir quelques termes de vocabulaire avec lesquels vous pouvez
ne pas être familier et que nous allons rencontrer tout au long de ce tuto :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Ascii : c'est l'acronyme de &lt;em&gt;American Standard Code for Information
Exchange&lt;/em&gt;, soit code américain pour l'échange d'information. Ce code permet de
représenter avec des nombres compris entre 0 et 127 les caractères utilisés
dans l'alphabet américain soit :&lt;ul&gt;
&lt;li&gt;Les lettres, minuscules et majuscules&lt;/li&gt;
&lt;li&gt;Les symboles de ponctuation : &lt;tt class="docutils literal"&gt;. , ;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Des caractères spéciaux : &lt;tt class="docutils literal"&gt;$ # * +&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Pas les accents&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Baud (Bd) : Unité de mesure du nombre de symboles transmissibles par
seconde. Il ne faut pas le confondre avec le nombre de bits par seconde
(bps). Par exemple, considérons que l'on souhaite transmettre le symbole ascii
&lt;tt class="docutils literal"&gt;a&lt;/tt&gt; en 1 seconde exactement. D'après la &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange#Table_des_128_caract.C3.A8res_ASCII"&gt;table ascii&lt;/a&gt;
&lt;tt class="docutils literal"&gt;a&lt;/tt&gt; s'écrit en binaire &lt;tt class="docutils literal"&gt;01100001&lt;/tt&gt;. Pour transmettre ce symbole en 1
seconde, il faut communiquer avec une vitesse de 1 Bd mais de 8 bps.&lt;/li&gt;
&lt;li&gt;Bytes (en python3) : Petite précision de vocabulaire spécifique à
python 3. C'est un type de base du langage qui représente une chaîne
d'octets. C'est ce type de donnée que nous manipulerons dans &lt;a class="reference internal" href="#communication-entre-un-programme-et-la-carte"&gt;communication
entre un programme et la carte&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="communiquer-avec-le-moniteur-serie"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id6"&gt;Communiquer avec le moniteur série&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Avant de rentrer vraiment dans la communication, je vous signale que deux
diodes présentes sur la arduino, peuvent être utiles :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;TX : s'allume lors d'une transmission&lt;/li&gt;
&lt;li&gt;RX : s'allume lors d'une réception&lt;/li&gt;
&lt;/ul&gt;
&lt;img alt="Une arduino et ses diodes TX et RX" class="center" src="/static/communication-serie/arduino-uno-TX-RX.jpg" style="width: 427.5px; height: 296.5px;" /&gt;
&lt;div class="section" id="communication-la-plus-simple-possible"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Communication la plus simple possible&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Nous allons aborder notre premier exemple. Il consiste à envoyer des données sur
le port série de la arduino de d'utiliser l'outil intégré à l'IDE pour voir les
données envoyées. Lancez l'éditeur arduino et entrez le code ci-dessous :&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Coucou&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Détaillons le :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Dans la fonction &lt;tt class="docutils literal"&gt;setup&lt;/tt&gt;, on initialise simplement le port série
en donnant sa vitesse avec &lt;tt class="docutils literal"&gt;Serial.begin(9600)&lt;/tt&gt;. En effet, pour que la carte
et l'ordinateur communique correctement, ils doivent « parler » à la même
vitesse. Une vitesse différente est une erreur fréquente au début. Pensez à la
vérifier si vous rencontrez des problèmes. On choisit ici 9600 Bd ce qui est une
valeur classique. Nous verrons plus loin l'&lt;a class="reference internal" href="#influence-du-nombre-de-bauds"&gt;influence du nombre de bauds&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Dans la fonction &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt;, on se contente d'envoyer &lt;tt class="docutils literal"&gt;&amp;quot;Coucou&amp;quot;&lt;/tt&gt; avec
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Serial.println(&amp;quot;Coucou&amp;quot;)&lt;/span&gt;&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vérifiez dans &lt;em&gt;Outils &amp;gt; Carte&lt;/em&gt; que la bonne carte est sélectionnée et dans
&lt;em&gt;Outils &amp;gt; Port série&lt;/em&gt; que le bon port est choisi. Si tout est bon, utilisez le
bouton &lt;em&gt;Téléchargements&lt;/em&gt; pour envoyer le code sur la carte.&lt;/p&gt;
&lt;p&gt;Ouvrez le moniteur série avec &lt;em&gt;Outils &amp;gt; Moniteur série&lt;/em&gt;. Vérifiez en bas à
droite que la valeur est bien à 9600 Bd. Si tout va bien, vous devriez voir le
moniteur se remplir de &lt;tt class="docutils literal"&gt;Coucou&lt;/tt&gt;.&lt;/p&gt;
&lt;img alt="Le moniteur série" class="center" src="/static/communication-serie/moniteur-serie.png" /&gt;
&lt;p&gt;Si ce n'est pas le cas, reprenez les étapes précédentes, vous avez raté quelque
chose. Vous pouvez aussi regarder du côté des &lt;a class="reference internal" href="#quelques-problemes-frequents"&gt;quelques problèmes fréquents&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="echo"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id8"&gt;Echo&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Après cet exemple d'autant moins intéressant qu'il ne fonctionne que dans un
sens, faisons un programme d'écho : la arduino va nous renvoyer exactement ce
qu'on lui envoie. Si elle ne reçoit rien, elle envoie &lt;tt class="docutils literal"&gt;Rien&lt;/tt&gt;. Voilà le code de
la arduino :&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Rien&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Regardons le d'un peu plus près. Pas de changement du côté de &lt;tt class="docutils literal"&gt;setup&lt;/tt&gt;. Dans
&lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Nous commençons par vérifier si des données en attente de lecture sur le port
avec : &lt;tt class="docutils literal"&gt;Serial.available()&lt;/tt&gt;. Cette fonction renvoie &lt;tt class="docutils literal"&gt;true&lt;/tt&gt; si telle est le
cas.&lt;/li&gt;
&lt;li&gt;Si on a des données, on définit une variable de type &lt;tt class="docutils literal"&gt;int&lt;/tt&gt; dans laquelle on
place une donnée en attente. Puis on affiche cette donnée.&lt;/li&gt;
&lt;li&gt;Sinon, on affiche &lt;tt class="docutils literal"&gt;Rien&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Enfin, on attend 2 secondes histoire d'avoir le temps de voir ce qui se passe.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Testez ce code. Pour envoyer une donnée à la carte, tapez du texte dans la barre
du haut puis presser &lt;em&gt;Entrée&lt;/em&gt; ou appuyez sur &lt;em&gt;Envoyer&lt;/em&gt;. Vous devriez obtenir
quelque chose comme ça (j'ai tapé &lt;em&gt;coucou&lt;/em&gt;) :&lt;/p&gt;
&lt;img alt="La réponse &amp;quot;écho&amp;quot; de la carte à &amp;quot;coucou&amp;quot;" class="center" src="/static/communication-serie/echo.png" /&gt;
&lt;p&gt;&lt;em&gt;Mais ce n'est pas ce que j'ai tapé !&lt;/em&gt; En effet, &lt;tt class="docutils literal"&gt;Serial.read()&lt;/tt&gt; lit un octet
de données sur le port série. Ni plus, ni moins. Et c'est la &lt;a class="reference external" href="http://arduino.cc/en/Serial/Read"&gt;seule manière&lt;/a&gt; de lire les données. Mais rassurez-vous,
vous pouvez facilement donner un sens à ce qui s'affiche : les données sont
encodées en ascii. Par conséquent, le numéro qui s'affiche est la version
décimale du code ascii. Vous pouvez consulter la &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/American_Standard_Code_for_Information_Interchange#Table_des_128_caract.C3.A8res_ASCII"&gt;table&lt;/a&gt;
pour convertir ce code dans le caractère standard.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="lire-des-entiers"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id9"&gt;Lire des entiers&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Dans cette partie, nous allons utiliser la table ascii pour convertir le nombre
reçu en quelque chose d'exploitable. Nous ferons tout d'abord un programme qui
lit et affiche correctement un nombre puis un second programme qui fera des
opérations sur deux entiers que vous choisirez.&lt;/p&gt;
&lt;div class="section" id="lecture-basique-d-un-entier"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id10"&gt;Lecture basique d'un entier&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ce n'est pas très compliqué. Il suffit de prendre la table ascii et de constater
que les chiffres sont codés en décimal entre 48 et 57 puis de décaler.&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;///&amp;lt; The current byte
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;recieved_integer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;///&amp;lt; The current recieved integer
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;is_a_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;ascii2int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;recieved_integer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;is_a_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;recieved_integer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ascii2int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recieved_integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;recieved_integer&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Détaillons ce programme :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;On définit les variables globales en début de programme. Ça ne sert à rien de
les redéfinir à chaque tour de boucle.&lt;/li&gt;
&lt;li&gt;Ensuite on définit deux fonctions :&lt;ul&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;boolean is_a_number(int n)&lt;/tt&gt; qui renvoie vrai si on lui donne un nombre
ascii codé en décimal.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;int ascii2int(int n, int byte_read)&lt;/tt&gt; qui renvoie le nombre sous la forme
d'un entier. Elle prend en paramètre l'entier déjà calculé ainsi que l'octet
à ajouter.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dans &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; : on fait la conversion si un entier est disponible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je vous laisse constater que ça marche bien.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="faire-des-maths-avec-deux-entiers"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id11"&gt;Faire des maths avec deux entiers&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Maintenant on va faire un peu mieux : lire deux entiers séparés par une virgule
et les additionner. Le code est ci-dessous :&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;///&amp;lt; The current byte read.
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;///&amp;lt; Contains x and y.
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;///&amp;lt; 0: reading x, 1: reading y.
&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;separator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;///&amp;lt; The separator between the integers (44: ,)
&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="n"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;is_a_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;ascii2int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;is_a_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byte_read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ascii2int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;byte_read&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;separator&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x + y = &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

      &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x * y = &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;coords&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Décortiquons :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Concernant les variables :&lt;ul&gt;
&lt;li&gt;Nos deux nombres seront stockés dans un tableau d'entier.&lt;/li&gt;
&lt;li&gt;&lt;tt class="docutils literal"&gt;index&lt;/tt&gt; nous permet de savoir si on lit x ou y.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dans &lt;tt class="docutils literal"&gt;loop&lt;/tt&gt; :&lt;ul&gt;
&lt;li&gt;On prend soin de remettre à 0 les variables pour éviter les problèmes.&lt;/li&gt;
&lt;li&gt;Puis suivant si l'octet lut représente un nombre ou le séparateur, on lit un
nombre ou on incrémente l'index.&lt;/li&gt;
&lt;li&gt;Concernant les calculs : on vérifie que &lt;tt class="docutils literal"&gt;index&lt;/tt&gt; n'est pas à 0 et donc
qu'on a bien lut deux nombres. Si tel est le cas, on fait l'addition et la
multiplication de x et y et on affiche le résultat. La fonction &lt;tt class="docutils literal"&gt;print&lt;/tt&gt;
affiche ses paramètres sans revenir à la ligne comme &lt;tt class="docutils literal"&gt;println&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous pouvez vous amuser à écrire une calculatrice plus complète si vous
voulez. Vous pouvez même envoyer l'opération à effectuer si vous
voulez. Utilisez éventuellement l'instruction &lt;a class="reference external" href="http://arduino.cc/en/Reference/SwitchCase"&gt;switch&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="communication-entre-un-programme-et-la-carte"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id12"&gt;Communication entre un programme et la carte&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cette partie reprend en partie ce qui a déjà été évoqué &lt;a class="reference external" href="//www.jujens.eu/posts/2014/Jan/11/communication-serie-facile-python/"&gt;ici&lt;/a&gt; mais de façon
plus détaillée et un peu moins complète.&lt;/p&gt;
&lt;div class="section" id="lecture"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id13"&gt;Lecture&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Nous allons maintenant faire communiquer un programme de votre ordinateur (autre
que l'IDE Arduino) et la carte. Le code sera écrit directement dans
l'interpréteur, mais vous pouvez sans problème le mettre dans un fichier puis
l'exécuter. Il sera écrit en python, mais les principes restent les mêmes dans
les autres langages. Reprenons le code « echo » pour la carte :&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Rien&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Lancez l'interpréteur python sur votre PC et importer la bibliothèque pyserial :&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="go"&gt;Python 3.3.2 (default, Mar  5 2014, 08:21:05)
[GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux
Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.
&lt;/span&gt;&lt;span class="kn"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Créez la communication série avec (en remplaçant &lt;tt class="docutils literal"&gt;/dev/ttyACM0&lt;/tt&gt; par le nom de
votre port) :&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="n"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;serial_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/dev/ttyACM0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour lire des données, rien de plus simple :&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="n"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;b'R'
&lt;/span&gt;&lt;span class="n"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;b'Rien\r\n'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Les résultats sont de type &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt;. Si vous comptez faire des manipulations
par la suite (hors transmission série), je vous conseille de passer dans le type
string plus adapté (ou un autre type qui représente correctement vos données) :&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="n"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt;
&lt;span class="go"&gt;b'Rien\r\n'
&lt;/span&gt;&lt;span class="nb"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;&amp;lt;class 'bytes'&amp;gt;
&lt;/span&gt;&lt;span class="n"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;chaine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ascii'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;chaine&lt;/span&gt;
&lt;span class="go"&gt;'Rien\r\n'
&lt;/span&gt;&lt;span class="nb"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chaine&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;&amp;lt;class 'str'&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="ecriture"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id14"&gt;Écriture&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Pour écrire des données c'est aussi très simple :&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="k"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="n"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Entrez un chiffre : '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ascii'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="n"&gt;serial_port&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;...&lt;/span&gt;
&lt;span class="go"&gt;Entrez un nombre : 78
1
b'55\r\n'&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Le nombre &lt;tt class="docutils literal"&gt;1&lt;/tt&gt; est la valeur de retour de &lt;tt class="docutils literal"&gt;serial_port.write&lt;/tt&gt; qui renvoie la
longueur de la chaîne écrite.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="influence-du-nombre-de-bauds"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id15"&gt;Influence du nombre de bauds&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Comme vous avez dû le comprendre en lisant &lt;a class="reference internal" href="#vocabulaire"&gt;vocabulaire&lt;/a&gt;, plus le nombre de
bauds est élevé, plus on peut transmettre de données dans un temps court. Nous
allons illustrer ceci dans cette partie. Télécharger tout d'abord le fichier
&lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/donnees.txt"&gt;donnee.txt&lt;/a&gt; qui contient
le texte à envoyer. Enregistrez de façon à pouvoir l'ouvrir facilement avec
l'interpréteur python. Programmez votre arduino avec le code suivant :&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;117500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Puis dans l'interpréteur python, tapez :&lt;/p&gt;
&lt;pre class="code pycon literal-block"&gt;
&lt;span class="n"&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/dev/ttyACM0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;117500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'donnees.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ascii'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;L'interpréteur devrait répondre rapidement &lt;tt class="docutils literal"&gt;8000&lt;/tt&gt;. Remplacez maintenant
&lt;tt class="docutils literal"&gt;117500&lt;/tt&gt; par &lt;tt class="docutils literal"&gt;4800&lt;/tt&gt; dans les deux codes. C'est &lt;strong&gt;beaucoup&lt;/strong&gt; plus long, non ?&lt;/p&gt;
&lt;p&gt;Le principal est d'utiliser la bonne vitesse de transmission pour son
application. Avec une grande vitesse, vous transmettez plus d'informations mais
cela peut poser des problèmes sur les grandes distances. À vous de tester et de
choisir la bonne, sachant qu'en général sur des cas simples, 9600 Bd est
suffisant.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id16"&gt;Conclusion&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;À partir de ces informations, vous devriez pouvoir faire ce que vous voulez tant
que ce n'est pas trop compliqué. Je publierais sûrement d'ici quelques temps un
tuto plus complet sur pyserial. En attendant, vous pouvez aller consulter la
&lt;a class="reference external" href="http://pyserial.sourceforge.net/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="en-resume"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id17"&gt;En résumé&lt;/a&gt;&lt;/h3&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Choisir la bonne vitesse de communication.&lt;/li&gt;
&lt;li&gt;Que les deux programmes qui communiquent le fasse à la même vitesse.&lt;/li&gt;
&lt;li&gt;Se souvenir que l'arduino lit les données en code ascii.&lt;/li&gt;
&lt;li&gt;Ne pas désespérer si ça ne fonctionne pas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="quelques-problemes-frequents"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id18"&gt;Quelques problèmes fréquents&lt;/a&gt;&lt;/h2&gt;
&lt;div class="section" id="probleme-de-telechargement"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id19"&gt;Problème de téléchargement&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ils sont malheureusement courants et je n'ai pas de méthode miracle pour les
régler. Vous pouvez :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Vérifiez le port de communication&lt;/li&gt;
&lt;li&gt;Débranchez/Re-branchez la carte&lt;/li&gt;
&lt;li&gt;Relancez l'éditeur&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="lecture-de-donnees-de-taille-indeterminees"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id20"&gt;Lecture de données de taille indéterminées&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Lors de tous nos tests de lecture, nous avons utilisé soit des int soit des
tableaux de taille fixe de int. Vous ne pouvez pas lire des données de taille
indéterminée avec la arduino. Par exemple, faire :&lt;/p&gt;
&lt;pre class="code cpp literal-block"&gt;
&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;En effet, contrairement à votre ordinateur qui a &lt;em&gt;beaucoup&lt;/em&gt; de mémoire, une
arduino est beaucoup plus limitée : pas plus de quelques kilos octets. La
lecture de données sous cette forme empêche le compilateur de connaître la
taille nécessaire pour la donnée et va donc refuser de compiler le code.&lt;/p&gt;
&lt;p&gt;Dans tous les cas, souvenez-vous que la mémoire est &lt;em&gt;très&lt;/em&gt; limitée et que vous
ne pourrez donc pas tout traiter.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="telechargements"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id21"&gt;Téléchargements&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tout est sous licence &lt;a class="reference external" href="http://www.apache.org/licenses/LICENSE-2.0.html"&gt;Apache v2&lt;/a&gt;.&lt;/p&gt;
&lt;ul class="simple" id="telechargement"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/serial_port_com/serial_port_com.ino"&gt;serial_port_com.ino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/lire_entier/lire_entier.ino"&gt;lire_entier.ino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/echo/echo.ino"&gt;echo.ino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/maths/maths.ino"&gt;maths.ino&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/baud/baud.ino"&gt;baud.ino&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L'archive avec tous les codes : &lt;a class="reference external" href="//www.jujens.eu/static/communication-serie/codes.zip"&gt;codes.zip&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Arduino - RPi - Robotique"></category><category term="Communication série"></category><category term="Arduino"></category><category term="Python"></category><category term="Robotique"></category></entry><entry><title>Mon passage à Pelican</title><link href="//www.jujens.eu/posts/2014/Apr/22/passage-pelican/" rel="alternate"></link><published>2014-04-22T00:00:00+02:00</published><updated>2014-04-22T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-04-22:/posts/2014/Apr/22/passage-pelican/</id><summary type="html">Un résumé de mon passage à Pelican, un générateur de sites statiques en python.</summary><content type="html">&lt;h1&gt;Présentation&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://getpelican.com"&gt;Pelican&lt;/a&gt; est un générateur de site statique écrit en python. Un générateur de site statique est simplement un programme qui transforme des fichiers textes en un site web avec thème, catégorie, … Les plus connus sont &lt;a href="http://jekyllrb.com/"&gt;jekyll&lt;/a&gt; qui est écrit en ruby, &lt;a href="http://middlemanapp.com/"&gt;middleman&lt;/a&gt; en ruby également, &lt;a href="http://octopress.org/"&gt;octopress&lt;/a&gt; qui est basé sur jekyll et &lt;a href="http://nanoc.ws/"&gt;nanoc&lt;/a&gt;. Mais il y en a beaucoup d'autres.&lt;/p&gt;

&lt;p&gt;L'avantage de ce genre de site est qu'ils sont simples, qu'ils n'ont pas besoin de bases de données ou de langages particuliers comme PHP sur votre serveur. Il faut juste un serveur web qui délivre des fichiers. Et ça, ils sont tous capables de le faire. J'ajouterais également la simplicité de rédaction : pas d'éditeur WYSIWYG, juste du texte brut et une syntaxe légère pour y donner du sens. Cela implique également que l'on peut utiliser un gestionnaire de version comme git ou mercurial pour gérer les fichiers (et pour en faire des sauvegardes facilement).&lt;/p&gt;

&lt;p&gt;Avant de passer à Pelican, j'ai pu tester Jekyll. Les deux sont très proches, très complets et extensibles via des plugins. Si j'ai préféré Pelican c'est parce que :&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Il est en python ce qui me permettra de faire des modifications ou des plugins au besoin (je ne connais pas suffisament ruby pour ça).&lt;/li&gt;
	&lt;li&gt;Il a un système de cache ce qui évite de devoir recompiller tout les fichiers à chaque fois.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;L’installation&lt;/h1&gt;
&lt;p&gt;Tout est très bien détaillé dans &lt;a href="http://docs.getpelican.com/en/3.3.0/getting_started.html"&gt;la documentation officielle&lt;/a&gt;. J'ai choisi la méthode recommandé : dans un enviromment virtuel, en python 3 (pour être moderne) et à partir de la version git (le plugin des commentaires statiques ne fonctionne pas bien sur la dernière version publiée).&lt;/p&gt;

&lt;p&gt;Attention toute fois, en python 3 la commande &lt;tt&gt; virtualenv &lt;/tt&gt; ne fonctionne pas comme il faut. J'ai utilisé la commande &lt;tt&gt; python3 -m venv blog &lt;/tt&gt; pour créer cet environement dans le dossier &lt;i&gt;blog&lt;/i&gt;. Le module &lt;i&gt;venv&lt;/i&gt; vient par défaut avec python 3. Reste à installer pelican et toutes les bibliothèques avec &lt;tt&gt; pip install &amp;lt;bibliothèque&amp;gt; &lt;/tt&gt;. Pelican a nottament besoin de Markdown. Les autres sont installées comme dépendance par pip. Le support d'Asciidoc demande un peu plus de travail. Allez voir la doc pour plus d'informations.&lt;/p&gt;

&lt;p&gt;Ensuite, la commande &lt;tt&gt; pelican-quickstart &lt;/tt&gt; va vous aider à générer la configuration du site. Vous allez devoir répondre à plusieurs questions pour que le site vous corresponde. Point intéressant, cette commande va aussi créer un Makefile pour vous aider à automatiser le processus de création de site. Plus d'infos ci-dessous.&lt;/p&gt;

&lt;h1&gt;Le site&lt;/h1&gt;
&lt;p&gt;Par défaut, Pelican supporte les articles écrits en markdown, RestructuredText ou dans une moindre mesure Asciidoc. On écrit simplement l'article dans le dossier &lt;i&gt;content&lt;/i&gt; (si vous avez lancez &lt;tt&gt; pelican-quickstart &lt;/tt&gt;) et on l'enregistre avec la bonne extension (.md pour du markdown ou .rst pour RestructuredText).&lt;/p&gt;

&lt;p&gt;Une fois l'article écrit, on lance la commande &lt;tt&gt; pelican chemin/vers/votre/article &lt;/tt&gt; et pelican va générer votre site statique dans un dossier nommé output. Si vous avez un Makefile, un simple &lt;tt&gt; make html &lt;/tt&gt; suffira. Pour visualiser votre site sur votre ordinateur, &lt;tt&gt; make serve &lt;/tt&gt; va lancer un serveur sur &lt;tt&gt; http://localhost:8000 &lt;/tt&gt;. Simple et efficace.&lt;/p&gt;

&lt;h1&gt;Les plugins et les thèmes&lt;/h1&gt;
&lt;p&gt;Un point intéressant : les fonctionnalités de Pelican peuvent être étendu via des plugins. Cela va de l'ajout d'un système de commentaires statiques au rendu des équations LaTeX en passant par une gallerie. Allez par &lt;a href="https://github.com/Scheirle/pelican-plugins"&gt;là&lt;/a&gt; pour en savoir plus.&lt;/p&gt;

&lt;p&gt;J'ai d'ailleur écrit mon propre plugin : creole-reader qui ajoute le support de la &lt;a href="http://en.wikipedia.org/wiki/Creole_%28markup%29"&gt;syntaxe creole&lt;/a&gt; dans pelican. Je ne suis en effet pas un grand fan de Markdown et la syntaxe Rest ne me plait que moyennement. Je crérais peut être aussi un plugin pour org-mode si je n'arrive pas à me faire à Rest (creole est beaucoup moins complet et trop limité pour des long tutos).&lt;/p&gt;

&lt;p&gt;Si vous pouvez créer facilement des thèmes à partir du moteur de template Jinja2, vous pouvez aussi prendre un des nombreux thèmes disponibles &lt;a href="https://github.com/Scheirle/pelican-themes"&gt;ici&lt;/a&gt;. J'ai choisi dev-random2 (que j'ai un peu adapté).&lt;/p&gt;

&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Mon passage à Pelican est récent mais je suis vraiment séduit par l'outil. Auparavant, mon blog était en Drupal. Cela peut paraître étrange, mais je gère une installation multisite de Drupal, donc ce n'était pas un problème. Par contre, Drupal manque de souplesse pour un blog. D'autant que sur notre installation, c'est soit du texte brut soit du HTML (éventuellement avec CKEditor). C'est d'autant plus pénible que CKeditor supporte très mal le code et à tendance à enlever certaines balise. Peu pratique, idem pour la gestion des révisions c'est pas souple même si ça marche très bien.&lt;/p&gt;

&lt;p&gt;Avec pelican, je suis très content de pouvoir utiliser du balisage léger et mercurial pour les révisions. Plus qu'à importer tout mes articles ;-).&lt;/p&gt;</content><category term="Blog"></category><category term="pelican"></category><category term="python"></category></entry><entry><title>Détecter une architecture avec CMake</title><link href="//www.jujens.eu/posts/2014/Apr/06/detecter-architecture-cmake/" rel="alternate"></link><published>2014-04-06T00:00:00+02:00</published><updated>2014-04-06T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-04-06:/posts/2014/Apr/06/detecter-architecture-cmake/</id><summary type="html">&lt;p&gt;Il est tout à fait possible de détecter l'architecture de l'hôte avec
CMake et d'adapter votre Makefile avec cette info. Il suffit d'utiliser
la variable &lt;em&gt;CMAKE_SYSTEM_PROCESSOR&lt;/em&gt;. Ci dessous un petit exemple :&lt;/p&gt;
&lt;pre class="code cmake literal-block"&gt;
&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CMAKE_SYSTEM_PROCESSOR&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;MATCHES&lt;/span&gt; &lt;span class="s"&gt;armv6l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;~/git/robidouille/raspicam_cv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;link_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_LIB_DIR&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;~/git/raspberrypi/userland/build/lib&lt;/span&gt; &lt;span class="s"&gt;~/git/robidouille …&lt;/span&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;Il est tout à fait possible de détecter l'architecture de l'hôte avec
CMake et d'adapter votre Makefile avec cette info. Il suffit d'utiliser
la variable &lt;em&gt;CMAKE_SYSTEM_PROCESSOR&lt;/em&gt;. Ci dessous un petit exemple :&lt;/p&gt;
&lt;pre class="code cmake literal-block"&gt;
&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CMAKE_SYSTEM_PROCESSOR&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;MATCHES&lt;/span&gt; &lt;span class="s"&gt;armv6l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;~/git/robidouille/raspicam_cv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;link_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_LIB_DIR&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;~/git/raspberrypi/userland/build/lib&lt;/span&gt; &lt;span class="s"&gt;~/git/robidouille/raspicam_cv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_LIBS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_LIBRARIES&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="s"&gt;raspicamcv&lt;/span&gt; &lt;span class="s"&gt;mmal_core&lt;/span&gt; &lt;span class="s"&gt;mmal&lt;/span&gt; &lt;span class="s"&gt;mmal_util&lt;/span&gt; &lt;span class="s"&gt;vcos&lt;/span&gt; &lt;span class="s"&gt;bcm_host&lt;/span&gt; &lt;span class="s"&gt;X11&lt;/span&gt; &lt;span class="s"&gt;Xext&lt;/span&gt; &lt;span class="s"&gt;rt&lt;/span&gt; &lt;span class="s"&gt;stdc++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;else&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nb"&gt;include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_LIBS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_LIBRARIES&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="CMake"></category><category term="C/C++"></category></entry><entry><title>Émuler une Raspberry Pi sous Linux avec Qemu</title><link href="//www.jujens.eu/posts/2014/Apr/06/emuler-rpi-linux-qemu/" rel="alternate"></link><published>2014-04-06T00:00:00+02:00</published><updated>2014-04-06T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-04-06:/posts/2014/Apr/06/emuler-rpi-linux-qemu/</id><summary type="html">&lt;p&gt;Qemu est un logiciel de virtualisation qui présente l'avantage de
pouvoir émuler de façon logicielle une architecture donnée. Il vous
permet donc de simuler une architecture que vous n'avez pas, par exemple
l'architecture arm sur x86. Qemu existe aussi sous windows, mais seule
la méthode sous linux sera évoquée ici …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Qemu est un logiciel de virtualisation qui présente l'avantage de
pouvoir émuler de façon logicielle une architecture donnée. Il vous
permet donc de simuler une architecture que vous n'avez pas, par exemple
l'architecture arm sur x86. Qemu existe aussi sous windows, mais seule
la méthode sous linux sera évoquée ici. Vous pouvez vous référer à &lt;a class="reference external" href="http://www.linux-mitterteich.de/fileadmin/datafile/papers/2013/qemu_raspiemu_lug_18_sep_2013.pdf"&gt;ce
document&lt;/a&gt;
pour la version windows. Je signale au passage que virt-manager ne
supporte pas a priori l'architecture arm1176. Voir par
&lt;a class="reference external" href="https://www.redhat.com/archives/virt-tools-list/2013-February/msg00115.html"&gt;là&lt;/a&gt;
pour plus d'infos.&lt;/p&gt;
&lt;div class="section" id="installer-qemu"&gt;
&lt;h2&gt;Installer Qemu&lt;/h2&gt;
&lt;p&gt;Tout d'abord, il faut installer qemu. Normalement, c'est présent dans
les dépôts de votre distribution. Sous Fedora, j'ai installé les paquets
suivants : qemu-system-arm et qemu-user. Vous devez avoir les commades
qemu-arm et qemu-system-arm une fois installé. Vérifiez que
l'achitecture arm1176 est bien supportée avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
qemu-arm -cpu ? | grep arm
&lt;/pre&gt;
&lt;p&gt;Vous devriez voir l'architecture correctement listée.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="recuperer-une-distribution-et-un-noyau"&gt;
&lt;h2&gt;Récupérer une distribution et un noyau&lt;/h2&gt;
&lt;p&gt;Récupérez une image de la distribution de votre choix sur le site qui va
bien : &lt;a class="reference external" href="http://www.raspberrypi.org/downloads"&gt;http://www.raspberrypi.org/downloads&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pour booter, vous allez aussi avoir besoin d'un noyau. Récuprérez le
avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
wget http://xecdesign.com/downloads/linux-qemu/kernel-qemu
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="augmenter-la-taille-de-l-image"&gt;
&lt;h2&gt;Augmenter la taille de l'image&lt;/h2&gt;
&lt;p&gt;Par défaut, les images des distributions sont très petites. Vous pourrez
faire quelques tests mais pas l'utiliser comme un vrai système émulé.
Pour cela, il faut augmenter la taille de l'image avec :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
qemu-img resize 2014-01-07-wheezy-raspbian.img +6G
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="demarrer-avec-un-shell-root-pour-regler-des-details"&gt;
&lt;h2&gt;Démarrer avec un shell root (pour régler des détails)&lt;/h2&gt;
&lt;p&gt;Lancez la commande ci-dessous pour démarrer. Vous aurez un clavier
qwerty. Ne changez pas la valeur après -m, qui représente la mémoire du
système. Il semble qu'elle soit hardcodée quelque part et une autre
valeur vous empêchera de démarrer.&lt;/p&gt;
&lt;pre class="literal-block"&gt;
qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -append &amp;quot;root=/dev/sda2 panic=1 init=/bin/sh rw&amp;quot; -hda 2014-01-07-wheezy-raspbian.img
&lt;/pre&gt;
&lt;p&gt;Éditez le fichiers /etc/ld.so.preload et commentez la première ligne
(maj + 3 pour faire un #) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
nano /etc/ld.so.preload
&lt;/pre&gt;
&lt;p&gt;Puis Ctlr-O pour sauvegarder et Ctrl-X pour quitter. Ce changement évite
le chargement de libcofi_rpi.so ce qui évite une boucle inifinie au
boot.&lt;/p&gt;
&lt;p&gt;Ensuite, on prépare les disques pour une utilisation future en créant
/etc/udev/rules.d/90-qemu.rules. Entrez les lignes suivantes dans ce
fichier :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
KERNEL==&amp;quot;sda&amp;quot;, SYMLINK+=&amp;quot;mmcblk0&amp;quot;
KERNEL==&amp;quot;sda?&amp;quot;, SYMLINK+=&amp;quot;mmcblk0p%n&amp;quot;,
&lt;/pre&gt;
&lt;p&gt;Terminez avec la commande sync pour être sûr que tout est écrit sur
l'image. Éditez également votre /etc/fstab : changez &lt;em&gt;mmcblk0p1 et
mmcblk0p2&lt;/em&gt;en respectivement &lt;em&gt;sda1&lt;/em&gt; et &lt;em&gt;sda2&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="demarrage-normal"&gt;
&lt;h2&gt;Démarrage normal&lt;/h2&gt;
&lt;p&gt;Entrez :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -append &amp;quot;root=/dev/sda2 panic=1&amp;quot; -hda 2014-01-07-wheezy-raspbian.img
&lt;/pre&gt;
&lt;p&gt;Si qemu vous demande de lancer fsck, entrez :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
fsck /dev/sda2 &amp;amp;&amp;amp; shutdown -r now
&lt;/pre&gt;
&lt;p&gt;Qemu devrait démarrer sur raspiconfig. Sélectionnez directement
&lt;em&gt;Finish&lt;/em&gt;. Nous allons maintenant agrandir les partitions. Avec&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo cfdisk /dev/sdb
&lt;/pre&gt;
&lt;p&gt;Supprimez la deuxième partition et recréez là avec tout l'espace
disponible. Ensuite, lancez (si les commandes ratent, redémarrez et
relancez les) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo resize2fs /dev/sdb2
sudo fsck -f /dev/sdb2
sudo halt
&lt;/pre&gt;
&lt;p&gt;C'est fini.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Arduino - RPi - Robotique"></category><category term="Raspberry Pi"></category><category term="Qemu"></category></entry><entry><title>CMake et drapeaux de compilation</title><link href="//www.jujens.eu/posts/2014/Mar/30/cmake-flags/" rel="alternate"></link><published>2014-03-30T00:00:00+01:00</published><updated>2014-03-30T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-03-30:/posts/2014/Mar/30/cmake-flags/</id><content type="html">&lt;p&gt;Pour ajouter des options à gcc, il suffit d'utiliser l'option set comme
ci dessous :&lt;/p&gt;
&lt;pre class="code cmake literal-block"&gt;
&lt;span class="c"&gt;# Compiler flags
&lt;/span&gt;&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;CMAKE_COMPILER_IS_GNUCXX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;CMAKE_CXX_FLAGS&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;-O2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c"&gt;## Optimize
&lt;/span&gt;    &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;CMAKE_EXE_LINKER_FLAGS&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;-s&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;## Strip binary
&lt;/span&gt;&lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
</content><category term="Programmation"></category><category term="CMake"></category><category term="C/C++"></category></entry><entry><title>Les bases de CMake</title><link href="//www.jujens.eu/posts/2014/Mar/29/bases-cmake/" rel="alternate"></link><published>2014-03-29T00:00:00+01:00</published><updated>2014-03-29T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-03-29:/posts/2014/Mar/29/bases-cmake/</id><summary type="html">&lt;p&gt;CMake est un utilitaire qui génère des MakeFile. Son principal intérêt
est d'avoir une syntaxe plus légère que le MakeFile de base. Les
bibliothèques les plus connues (Boost, OpenCV, …) sont compatibles avec
ce système. Ci dessous un petit exemple pour vous aider à démarrer. Il faut
enregistrer le contenu du …&lt;/p&gt;</summary><content type="html">&lt;p&gt;CMake est un utilitaire qui génère des MakeFile. Son principal intérêt
est d'avoir une syntaxe plus légère que le MakeFile de base. Les
bibliothèques les plus connues (Boost, OpenCV, …) sont compatibles avec
ce système. Ci dessous un petit exemple pour vous aider à démarrer. Il faut
enregistrer le contenu du fichier dans &lt;tt class="docutils literal"&gt;CMakeLists.txt&lt;/tt&gt; puis dans le dossier
où vous voulez produire vos binaires, entrez : &lt;tt class="docutils literal"&gt;cmake VERS_CMakeLists.txt&lt;/tt&gt;&lt;/p&gt;
&lt;pre class="code cmake literal-block"&gt;
&lt;span class="nb"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;cmake_minimum_required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;VERSION&lt;/span&gt; &lt;span class="s"&gt;2.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;FIND_PACKAGE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;OpenCV&lt;/span&gt; &lt;span class="s"&gt;REQUIRED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;FIND_PACKAGE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;Boost&lt;/span&gt; &lt;span class="s"&gt;COMPONENTS&lt;/span&gt; &lt;span class="s"&gt;system&lt;/span&gt; &lt;span class="s"&gt;filesystem&lt;/span&gt; &lt;span class="s"&gt;REQUIRED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_INCLUDE_DIRS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;link_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_LIB_DIR&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_LIBRARY_DIR&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;aux_source_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt; &lt;span class="s"&gt;SRC_LIST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;add_executable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SRC_LIST&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OpenCV_LIBS&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Boost_LIBRARIES&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Et voilà un CMakeLists.txt basique. À vous de creuser pour en faire des plus complexes.&lt;/p&gt;
</content><category term="Programmation"></category><category term="CMake"></category><category term="C/C++"></category></entry><entry><title>Compilation conditionnelle avec CMake</title><link href="//www.jujens.eu/posts/2014/Mar/29/compilation-conditionnelle-cmake/" rel="alternate"></link><published>2014-03-29T00:00:00+01:00</published><updated>2014-03-29T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-03-29:/posts/2014/Mar/29/compilation-conditionnelle-cmake/</id><summary type="html">&lt;p&gt;Lorsqu'on fait de gros programme C ou C++, il peut être intéressant de
ne compiler une partie du programme que si une option est passée en
argument. Nous allons voir comment le faire en utilisant
&lt;a class="reference external" href="http://fr.wikipedia.org/wiki/CMake"&gt;CMake&lt;/a&gt;, un générateur de
MakeFile très connu et très puissant. &lt;a class="reference external" href="/clubrobot/content/les-bases-de-cmake"&gt;Voir notre article sur
CMake …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;Lorsqu'on fait de gros programme C ou C++, il peut être intéressant de
ne compiler une partie du programme que si une option est passée en
argument. Nous allons voir comment le faire en utilisant
&lt;a class="reference external" href="http://fr.wikipedia.org/wiki/CMake"&gt;CMake&lt;/a&gt;, un générateur de
MakeFile très connu et très puissant. &lt;a class="reference external" href="/clubrobot/content/les-bases-de-cmake"&gt;Voir notre article sur
CMake&lt;/a&gt; pour les bases de
CMake.&lt;/p&gt;
&lt;p&gt;Considérons pour cet article, que le programme doit afficher &lt;em&gt;coucou&lt;/em&gt; si
l'option est présente et rien sinon. Entourons remplaçons simplement la
ligne `` std::cout &amp;lt;&amp;lt; &amp;quot;coucou&amp;quot; &amp;lt;&amp;lt; std::endl; `` par :&lt;/p&gt;
&lt;pre class="code c++ literal-block"&gt;
&lt;span class="cp"&gt;#if defined(COUCOU)
&lt;/span&gt;    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;coucou&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Il est tout à fait possible d'utiliser &lt;tt class="docutils literal"&gt;#ifdef&lt;/tt&gt; à la place de
&lt;tt class="docutils literal"&gt;#if defined&lt;/tt&gt; mais on ne peut alors imbriquer les conditions :
&lt;tt class="docutils literal"&gt;#if ( defined(COUCOU) &amp;amp;&amp;amp; defined(SALUT) )&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Il n'y a plus qu'à ajouter dans le CMakeLists.txt :&lt;/p&gt;
&lt;pre class="code cmake literal-block"&gt;
&lt;span class="nb"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;COUCOU&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Active coucou&amp;quot;&lt;/span&gt; &lt;span class="s"&gt;OFF&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;COUCOU&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;MESSAGE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;STATUS&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;COUCOU SUPPORT&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;add_definitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;-DCOUCOU&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour compiler, utilisez simplement :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Pour activer COUCOU : &lt;tt class="docutils literal"&gt;cmake .. &lt;span class="pre"&gt;-DCOUCOU=on&lt;/span&gt; &amp;amp;&amp;amp; make&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Pour ne pas activer COUCOU : &lt;tt class="docutils literal"&gt;cmake .. &lt;span class="pre"&gt;-DCOUCOU=off&lt;/span&gt; &amp;amp;&amp;amp; make&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><category term="Programmation"></category><category term="Make"></category><category term="CMake"></category><category term="C/C++"></category></entry><entry><title>Utiliser ipython pour manipuler des espaces en shell</title><link href="//www.jujens.eu/posts/2014/Mar/09/utiliser-ipython-manipuler-espaces-shell/" rel="alternate"></link><published>2014-03-09T00:00:00+01:00</published><updated>2014-03-09T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-03-09:/posts/2014/Mar/09/utiliser-ipython-manipuler-espaces-shell/</id><summary type="html">&lt;p&gt;Bash est assez pénible quand à la gestion des espaces. Par défaut, la
boucle for itère sur ce qui est séparé par un saut de ligne ou un
espace. Je n'ai pas encore trouvé de solution satisfaisante en bash pur.
Mais python (ou plutôt ipthon peut venir à la rescousse …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Bash est assez pénible quand à la gestion des espaces. Par défaut, la
boucle for itère sur ce qui est séparé par un saut de ligne ou un
espace. Je n'ai pas encore trouvé de solution satisfaisante en bash pur.
Mais python (ou plutôt ipthon peut venir à la rescousse). Ipython est un
shell interactif pour python. Vous pouvez y appeler n'importe quelle
commande bash directement via la syntaxe !cmd. Avec a = !cmd, la sortie
de cmd est stocké dans une liste constitué de chaque ligne de la sortie.
Pour voir ce qu'aurait contenu a sans l'affectée, il suffit d'utiliser
la syntaxe : !!cmd.&lt;/p&gt;
&lt;p&gt;Les présentations étant faites, voici un petit script pour renommer des
fichiers avec des espaces en ipython. Il s'adapte faciliment à d'autres
situations :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env ipython3&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;
&lt;span class="c1"&gt;# Les variables contiennent des espaces, on les entoure donc avec des guillements&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;$file&amp;quot;&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="Bash/Shell"></category><category term="python"></category><category term="ipython"></category></entry><entry><title>Drupal : un an d'utilisation, mes impressions</title><link href="//www.jujens.eu/posts/2014/Feb/01/drupal-an-utilisation-impressions/" rel="alternate"></link><published>2014-02-01T00:00:00+01:00</published><updated>2014-02-01T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-02-01:/posts/2014/Feb/01/drupal-an-utilisation-impressions/</id><summary type="html">&lt;p class="first last"&gt;Je suis utilisateur de &lt;a class="reference external" href="http://drupal.org"&gt;Drupal&lt;/a&gt; depuis environ 1 an maintenant et j’ai donc décidé de partager ce que j’ai appris avec cet outil que j’ai découvert à Centrale Marseille (ECM) grâce au  &lt;a class="reference external" href="http://assos.centrale-marseille.fr"&gt;projet multi-assos&lt;/a&gt;. Aujourd’hui, j’admets avoir pris goût à l’outil et je suis le webmaster du forum foceen un des plus gros sites de l’installation (et un des plus compliqué aussi).&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Je suis utilisateur de &lt;a class="reference external" href="http://drupal.org"&gt;Drupal&lt;/a&gt; depuis environ 1
an maintenant et j’ai donc décidé de partager ce que j’ai appris avec
cet outil que j’ai découvert à Centrale Marseille (ECM) grâce au &lt;a class="reference external" href="http://assos.centrale-marseille.fr"&gt;projet
multi-assos&lt;/a&gt; (qui héberge cet
humble blog). Aujourd’hui, j’admets avoir pris goût à l’outil et je suis
le webmaster du forum foceen un des plus gros sites de l’installation
(et un des plus compliqué aussi).&lt;/p&gt;
&lt;div class="section" id="avant"&gt;
&lt;h2&gt;Avant&lt;/h2&gt;
&lt;p&gt;Avant d’entrer à l’ECM, je n’avais jamais fait de vrai site web. J’avais
appris quelques bases de php et de mysql sur le site du zéro
(&lt;a class="reference external" href="http://fr.openclassrooms.com/"&gt;openclassrooms&lt;/a&gt; maintenant). J’avais
un peu entendu parler de framework et de&amp;nbsp;CMS mais je n’en pensais pas
grand chose de bien. Sans trop caricatirer, je pensais : &lt;em&gt;« Non mais un
site ça se code à la main. Les CMS et les framework c’est des machins
d’assistés&amp;nbsp;»&lt;/em&gt;. Et puis j'ai découvert Drupal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="id1"&gt;
&lt;h2&gt;Drupal&lt;/h2&gt;
&lt;p&gt;Si vous ne connaissez pas encore &lt;a class="reference external" href="http://drupal.org"&gt;Drupal&lt;/a&gt;,
permettez que je vous présente l'outil. C'est un des CMS les plus
utilisés et les plus populaires. Drupal accueille de gros sites (comme
celui de la maison blanche) et des plus modestes (comme celui-ci) et
globalement de nombreux sites d'entreprises ou d'institutions.&lt;/p&gt;
&lt;p&gt;Un des gros avantages de Drupal est sa modularité. Sa communauté très
active maintient de très nombreux modules de qualité qui vous permettent
de transformer votre Drupal en site de e-commerce, en forum ou plus
simplement de lui ajouter des fonctionnalités intéressantes comme un
éditeur WYSIWYG. Le tout sans coder une seule ligne. De plus, ces
modules viennent avec des interfaces puissantes mais bien faîtes pour
les configurer suivant vos besoins. Le tout juste avec votre souris. Ce
qui signifie que vous n'avez pas besoin d'être un geek pour être
webmaster d'un site. Tout ce fait très bien via l'interface (sauf pour
des besoins très spécifiques qui demandent du dévelloppement).&lt;/p&gt;
&lt;p&gt;La communauté crée aussi pleins de thèmes et certains sont mêmes
adaptatifs. Pas besoin d'être un très bon designer pour avoir un joli
site. Plutôt cool non ?&lt;/p&gt;
&lt;p&gt;Ce sont toutes ces raisons qui font que Drupal est bien adapté pour les
associations de l'école. On est pas des dévelopeurs et cela permet de
péréniser les sites web. Car c'est dur de faire un site web (du moins
correctement).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="administrer-l-installation"&gt;
&lt;h2&gt;Administrer l'installation&lt;/h2&gt;
&lt;p&gt;En tant que membre du club Drupal, je fais des sites web (et aide ceux
qui en font) et administre l'installation. C'est à mon avis la partie la
plus intéressante.&lt;/p&gt;
&lt;p&gt;Faire des scripts Shell pour automatiser des tâches, faire du git,
monter un serveur en local, bosser sur les migartions de drupal,… c'est
intéressant et formateur (surtout quand il ne faut rien casser).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="c-est-dur-de-faire-un-site-web"&gt;
&lt;h2&gt;C'est dur de faire un site web&lt;/h2&gt;
&lt;p&gt;Contrairement à ce que peut laisser penser un cours de PHP ce n'est pas
simple de faire un site web correctement. Ma (certes assez petite)
expérience de webmaster me l'a bien montrée. Sur un site fait par
quelqu'un qui est reconnu comme plutôt bon et qui sait coder, il peut y
avoir de nombreux problèmes.&lt;/p&gt;
&lt;p&gt;Ceux que j'ai vu et qui m'ont posés le plus de problèmes sont :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;du code non indenté&lt;/li&gt;
&lt;li&gt;les mots de passe stockés en clair dans la base de données (si si, il
y en a qui le font)&lt;/li&gt;
&lt;li&gt;des accès base de données sans passer par PDO (donc pas de requêtes
préparées et des injections SQL faciles à faire)&lt;/li&gt;
&lt;li&gt;des données encodées n'importe comment dans une base de données&lt;/li&gt;
&lt;li&gt;fonction_1, fonction_2 et fonction_3 qui font la même chose (en
tout cas je n'ai pas vu la différence). Et la gestion de version ça
sert à quoi ?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Drupal c'est bien ;-). Vous vous prendrez la tête sur l'interface au
lieu de vous prendre la tête sur du code mais bon, vous surviverez. Vous
tomberez aussi sur des gens qui pense que comme tout se fait à la souris
c'est facile et ça ne s'apprend pas. Ça c'est faux. Il vont faire des
pages entièrement codé en html sans utiliser les champs et les vues. Ils
vous dirons que Drupal c'est pourri et qu'en PHP ils auraient pu le
faire facilement. On ne peut pas tout résoudre avec un outil, aussi bien
soit-il.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="Drupal"></category></entry><entry><title>Mettre sous git sous Drupal</title><link href="//www.jujens.eu/posts/2014/Feb/01/mettre-drupal-sous-git/" rel="alternate"></link><published>2014-02-01T00:00:00+01:00</published><updated>2014-02-01T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-02-01:/posts/2014/Feb/01/mettre-drupal-sous-git/</id><summary type="html">&lt;p&gt;Récemment j'ai mis l'install Drupal du projet &lt;a class="reference external" href="http://assos.centrale-marseille.fr"&gt;multi
assos&lt;/a&gt; sous git (vous pouvez
aussi utiliser un autre DVCS si vous voulez). Voilà mon petit compte
rendu.&lt;/p&gt;
&lt;div class="section" id="interet"&gt;
&lt;h2&gt;Intérêt&lt;/h2&gt;
&lt;p&gt;La première question que vous vous poserez sûrement est pourquoi placer
Drupal sous git ? Parce que c'est utile. Cela :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;vous permet de suivre …&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Récemment j'ai mis l'install Drupal du projet &lt;a class="reference external" href="http://assos.centrale-marseille.fr"&gt;multi
assos&lt;/a&gt; sous git (vous pouvez
aussi utiliser un autre DVCS si vous voulez). Voilà mon petit compte
rendu.&lt;/p&gt;
&lt;div class="section" id="interet"&gt;
&lt;h2&gt;Intérêt&lt;/h2&gt;
&lt;p&gt;La première question que vous vous poserez sûrement est pourquoi placer
Drupal sous git ? Parce que c'est utile. Cela :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;vous permet de suivre les évolutions de l'installation : mise à jour,
installation/suppression de module.&lt;/li&gt;
&lt;li&gt;vous fournit un moyen simple de revenir en arrière en cas de
problèmes (mauvaise mise à jour)&lt;/li&gt;
&lt;li&gt;vous permet de comparer les différentes versions de vos settings.php
et .htaccess&lt;/li&gt;
&lt;li&gt;savoir qu'un fichier utile (comme un .htaccess) a disparu&lt;/li&gt;
&lt;li&gt;faire des tests en local facilement et les pusher sur le seveur s'ils
sont concluants.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="preparations"&gt;
&lt;h2&gt;Préparations&lt;/h2&gt;
&lt;p&gt;La question qui doit nous guider lors de cette étape est : que devons
placer sous git ? En effet, il ne faut pas faire un brutal &lt;em&gt;git add
drupal&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Que contient une installation de Drupal ?&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Drupal en lui même&lt;/li&gt;
&lt;li&gt;Les modules et thèmes&lt;/li&gt;
&lt;li&gt;Les dossiers des sites qui contiennent&lt;ul&gt;
&lt;li&gt;un settings.php&lt;/li&gt;
&lt;li&gt;les fichiers du sites&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nous voulons tous suivre sauf les fichiers du site (parce qu'ils
changent tous de temps et n'ont rien à faire dans le dépôt) et les
données de connexion à la base de données pour chacun des sites.&lt;/p&gt;
&lt;p&gt;Nous devons modifier la façon dont Drupal gère les settings.php pour que
les mots de passes de la base de données ne se retrouvent pas dans le
dépôt. Pour ce faire :&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;créez dans le dossier sites un fichier settings.global.php. Ce
fichier sera commun à tous les sites. Déplacez-y toutes les
informations génériques (commentaires, les fonctions qui permettent
de configurer PHP) et tout ce qui touche à la sécurité.&lt;/li&gt;
&lt;li&gt;créez dans chaque dossier de site un fichier settings.local.php et
placez-y les informations spécifiques au site (accès base de données,
base url,…)&lt;/li&gt;
&lt;li&gt;remplacez le contenu du settings.php par ceci :&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// Load the global settings file.&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="nb"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/../settings.global.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Load the local settings file with databases connexion.&lt;/span&gt;
&lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="nb"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/settings.local.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ceci étant fait, préparons le .gitignore. Nous devons y ajouter les
dossiers des sites. (default et assos.centrale-marseille.fr.* pour
nous). Apdaptez à votre installation.&lt;/p&gt;
&lt;p&gt;Reste également vos scripts éventuels. De notre côté plusieurs ont dû
être modifiés. La liste est là (par ordre chronologique) :&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/repository/revisions/1c1c5a429b70f697d7504e5a30f92594fa388ff0"&gt;https://forge.centrale-marseille.fr/projects/clubdrupal/repository/revisions/1c1c5a429b70f697d7504e5a30f92594fa388ff0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/repository/revisions/c01204bf932788df810f08d9d3b2ffe828bd94de"&gt;https://forge.centrale-marseille.fr/projects/clubdrupal/repository/revisions/c01204bf932788df810f08d9d3b2ffe828bd94de&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/repository/revisions/6d91f38e4a472a3e517b86e4a66c31e18e018bd3"&gt;https://forge.centrale-marseille.fr/projects/clubdrupal/repository/revisions/6d91f38e4a472a3e517b86e4a66c31e18e018bd3&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class="section" id="le-passage"&gt;
&lt;h2&gt;Le passage&lt;/h2&gt;
&lt;p&gt;Maintenant que nous sommes prêts, il n'y a plus qu'à faire un petit &lt;em&gt;git
add&lt;/em&gt; et de faire votre premier commit. Pensez à commiter dès que vous
faîtes un changement dans votre installation (avec des scripts au
besoin).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;On sait enfin ce qui se passe et on est certain de pouvoir revenir en
arrière facilement au besoin. Vous pouvez évidement mettre vos scripts,
template, … dans le dépôt. De notre côté, on a aussi un script pour
synchroniser un site et faire des tests dessus en local. Il est
&lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/repository/changes/other-scripts/d7-sync.sh?rev=master"&gt;ici&lt;/a&gt;
(et sa dépendance
&lt;a class="reference external" href="https://forge.centrale-marseille.fr/projects/clubdrupal/repository/changes/other-scripts/modify-settings.py?rev=master"&gt;ici&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="Drupal"></category><category term="git"></category></entry><entry><title>Relier sa Raspberry Pi à son PC directement en Ethernet</title><link href="//www.jujens.eu/posts/2014/Jan/12/relier-rpi-pc-ethernet/" rel="alternate"></link><published>2014-01-12T00:00:00+01:00</published><updated>2014-01-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-01-12:/posts/2014/Jan/12/relier-rpi-pc-ethernet/</id><summary type="html">&lt;p&gt;Dans cet article, nous allons étudier comment connecter son Raspberry Pi
directement à son PC pour&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;pouvoir s'y connecter en SSH&lt;/li&gt;
&lt;li&gt;qu'il ait une connection internet (via le wifi de notre PC)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-le-reseau" id="id1"&gt;Configurer le réseau&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#methode-graphique-avec-networkmanager" id="id2"&gt;Méthode graphique avec NetworkManager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#en-ligne-de-commande" id="id3"&gt;En ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-le-pare-feu" id="id4"&gt;Configurer le pare feu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurons-la-raspberry-pi-pour-le-reseau" id="id5"&gt;Configurons la …&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Dans cet article, nous allons étudier comment connecter son Raspberry Pi
directement à son PC pour&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;pouvoir s'y connecter en SSH&lt;/li&gt;
&lt;li&gt;qu'il ait une connection internet (via le wifi de notre PC)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="contents topic" id="sommaire"&gt;
&lt;p class="topic-title"&gt;Sommaire&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-le-reseau" id="id1"&gt;Configurer le réseau&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#methode-graphique-avec-networkmanager" id="id2"&gt;Méthode graphique avec NetworkManager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#en-ligne-de-commande" id="id3"&gt;En ligne de commande&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurer-le-pare-feu" id="id4"&gt;Configurer le pare feu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#configurons-la-raspberry-pi-pour-le-reseau" id="id5"&gt;Configurons la Raspberry Pi pour le réseau&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="reference internal" href="#avec-un-serveur-dhcp" id="id6"&gt;Avec un serveur DHCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#pour-une-ip-fixe" id="id7"&gt;Pour une IP fixe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#pidora" id="id8"&gt;Pidora&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#raspbian" id="id9"&gt;Raspbian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#et-voila" id="id10"&gt;Et voilà&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#en-plus" id="id11"&gt;En plus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference internal" href="#sources" id="id12"&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-le-reseau"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id1"&gt;Configurer le réseau&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Le Raspberry Pi et le PC doivent être sur la même plage d'adresse IP
pour pouvoir communiquer mais pas sur la même plage d'adresse que
l'interface wifi (sinon il y a conflit). Dans la suite, je vais
configurer les interfaces éthernet sur 192.168.1.* le wifi étant géré
automatiquement par votre gestionnaire habituel (NetworkManager chez
moi). Je ne détaillerai que la connexion en IP fixe qui fonctionne très
bien mais qui peux être lourde si vous avez beaucoup de machine à
configurer. Il vous faudra alors regarder comment installer un &lt;a class="reference external" href="http://fr.wikipedia.org/wiki/DHCP"&gt;serveur
DHCP&lt;/a&gt; par exemple en suivant les
instructions données
&lt;a class="reference external" href="http://doc.fedora-fr.org/wiki/Mise_en_place_d%27un_serveur_DHCP_Simple"&gt;ici&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="methode-graphique-avec-networkmanager"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id2"&gt;Méthode graphique avec NetworkManager&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a class="reference external" href="http://fr.wikipedia.org/wiki/NetworkManager"&gt;NetworkManager&lt;/a&gt; permet
de gérer les réseaux plutôt facilement. Ouvrez la fenêtre de
configuration et cliquez sur &lt;em&gt;réseaux filaires&lt;/em&gt;. Choisissez &lt;em&gt;Ajoutez un
profil&lt;/em&gt;. Dans la section &lt;em&gt;Identité&lt;/em&gt;, donnez un nom au profil et cochez
&lt;em&gt;Connecter automatiquement&lt;/em&gt;. Dans la section &lt;em&gt;IPV4&lt;/em&gt;, changez &lt;em&gt;Automatic
(DHCP)&lt;/em&gt; en &lt;em&gt;Manuel&lt;/em&gt;. Entrez l'adresse IP que vous désirez associer à
cette interface. Dans mon cas : 192.168.1.1, le masque de sous réseau :
255.255.255 et la route par défaut : 192.168.1.1.&lt;/p&gt;
&lt;p&gt;Cochez &lt;em&gt;Use this connection only for resources on its network.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Enregistrez et activez cette interface.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="en-ligne-de-commande"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id3"&gt;En ligne de commande&lt;/a&gt;&lt;/h3&gt;
&lt;pre class="code bash literal-block"&gt;
sudo ip addr add &lt;span class="m"&gt;192&lt;/span&gt;.168.1.1/24 dev eth0
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="configurer-le-pare-feu"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id4"&gt;Configurer le pare feu&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Il faut maintenant autoriser la connexion et rediriger le traffic de la
raspberry pi vers l'interface wifi. Pour cela, on entre les commandes
suivantes :&lt;/p&gt;
&lt;pre class="code literal-block"&gt;
sudo iptables -A FORWARD -o wlan0 -i eth0 -s 192.168.1.0/24 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A POSTROUTING -t nat -j MASQUERADE
&lt;/pre&gt;
&lt;p&gt;Ou sous Fedora (ou tout autre système utilisant firewalld)&lt;/p&gt;
&lt;pre class="literal-block"&gt;
firewall-cmd --zone=public --add-masquerade
&lt;/pre&gt;
&lt;p&gt;À titre d'information : sous Fedora, les trois commandes précédentes
permettent de se connecter en SSH à la Raspberry Pi, de pinger une IP
depuis la Raspberry Pi mais pas un nom de domaine. Après un certain
temps à chercher du côté du resolv.conf, c'est grâce à la commande &lt;em&gt;dig
centrale-marseille.fr &amp;#64;8.8.8.8&lt;/em&gt; que j'ai pu voir que le problème était
d'un autre ordre. Étrangement cette commande ne vient pas par défaut
sous &lt;a class="reference external" href="http://raspbian.org/"&gt;Raspbian&lt;/a&gt;. Elle est en revanche présente
sous &lt;a class="reference external" href="http://pidora.ca/"&gt;Pidora&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Si vous rencontrez des problèmes, sachez que la commande &lt;em&gt;iptables -F&lt;/em&gt;
enlève toutes les règles du parefeu.&lt;/p&gt;
&lt;p&gt;Pensez également à vérifier que votre système autorise le transfert d'IP&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sysctl -a | grep ip_forward
&lt;/pre&gt;
&lt;p&gt;Si la réponse est :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
net.ipv4.ip_forward = 0
&lt;/pre&gt;
&lt;p&gt;faîtes, pour autoriser ce paramétrage :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sysctl net.ipv4.ip_forward = 1
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="configurons-la-raspberry-pi-pour-le-reseau"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id5"&gt;Configurons la Raspberry Pi pour le réseau&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Il y a deux méthodes pour avoir du réseau : l'IP fixe qui implique de
configurer la Raspberry Pi et l'IP attribuée par un serveur DHCP qui
tourne sur votre machine (ce qui implique de le configurer mais permet
d'installer sa rapsberry pi sans écran).&lt;/p&gt;
&lt;div class="section" id="avec-un-serveur-dhcp"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id6"&gt;Avec un serveur DHCP&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Installez le paquet dhcp qui devrait être présent dans les dépôts de
votre distribution. Éditez ensuite le fichier /etc/dhcp/dhcpd.conf. Il
doit ressembler à :&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="c1"&gt;#
# DHCP Server Configuration file.
#   see /usr/share/doc/dhcp/dhcpd.conf.example
#   see dhcpd.conf(5) man page
#
&lt;/span&gt;&lt;span class="k"&gt;subnet&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.0&lt;/span&gt; &lt;span class="s"&gt;netmask&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="s"&gt;.255.255.0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kn"&gt;option&lt;/span&gt; &lt;span class="s"&gt;routers&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;# passerelle par défaut
&lt;/span&gt;        &lt;span class="kn"&gt;option&lt;/span&gt; &lt;span class="s"&gt;domain-name-servers&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="s"&gt;.8.8.8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c1"&gt;# serveurs DNS
&lt;/span&gt;        &lt;span class="kn"&gt;range&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.2&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;# plage d’adresse
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour donner une adresse fixe à un hôte (l'adresse mac est requise) :&lt;/p&gt;
&lt;pre class="code nginx literal-block"&gt;
&lt;span class="k"&gt;subnet&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.0&lt;/span&gt; &lt;span class="s"&gt;netmask&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="s"&gt;.255.255.0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kn"&gt;option&lt;/span&gt; &lt;span class="s"&gt;routers&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;# passerelle par défaut
&lt;/span&gt;        &lt;span class="kn"&gt;option&lt;/span&gt; &lt;span class="s"&gt;domain-name-servers&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="s"&gt;.8.8.8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c1"&gt;# serveurs DNS
&lt;/span&gt;        &lt;span class="kn"&gt;host&lt;/span&gt; &lt;span class="s"&gt;daneel.egab&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;hardware&lt;/span&gt; &lt;span class="s"&gt;ethernet&lt;/span&gt; &lt;span class="n"&gt;b8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;eb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;ca:ee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;fixed-address&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="kn"&gt;range&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.2&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="s"&gt;.168.1.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;# plage d’adresse
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Le bloc host qui donne l'ip fixe doit être avant la directive range&lt;/p&gt;
&lt;p&gt;Il n'y a plus qu'à lancer le serveur dhcp avec la commande
&lt;tt class="docutils literal"&gt;systemctl start dhcpd&lt;/tt&gt;. Pour savoir quelle est l'adresse atribuée à
la Raspberry, consultez les log : &lt;tt class="docutils literal"&gt;journalctl &lt;span class="pre"&gt;-f&lt;/span&gt; /usr/sbin/dhcpd&lt;/tt&gt; ou
&lt;tt class="docutils literal"&gt;tail &lt;span class="pre"&gt;-f&lt;/span&gt; /var/log/messages&lt;/tt&gt; si vous n'utilisez pas journald.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pour-une-ip-fixe"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id7"&gt;Pour une IP fixe&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Mainteant, au tour de la Raspberry Pi de recevoir sa conf.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="pidora"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id8"&gt;Pidora&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ouvrez /etc/sysconfig/network-scripts/ifcfg-eth0 et entrez (remplacez
les instructions déjà présentes au besoin) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
DEVICE=eth0
BOOTPROTO=none
BROADCAST=192.168.1.255
ONBOOT=yes
USERCTL=no
DNS=8.8.8.8
PEERDNS=yes
IPV6INIT=no
NM_CONTROLLED=no
NETMASK=255.255.255.0
IPADDR=192.168.1.2
GATEWAY=192.168.1.1
TYPE=Ethernet
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="raspbian"&gt;
&lt;h3&gt;&lt;a class="toc-backref" href="#id9"&gt;Raspbian&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ouvrez /etc/network/interfaces et entrez (en ne modifiant que les lignes
concernant l'interface eth0) :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
auto eth0
iface eth0 inet static
        address 192.0.2.7
        netmask 255.255.255.0
        gateway 192.0.2.254
        dns-nameservers 8.8.8.8
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="et-voila"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id10"&gt;Et voilà&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Normalement tout fonctionne. J'espère que cet article vous a été utile.
Si vous avez des questions ou des remarques, n'hésitez pas ;-).&lt;/p&gt;
&lt;p&gt;Si vous avez des problèmes avec la résolutions des noms de domaine,
entrez dans /etc/resolv.conf&lt;/p&gt;
&lt;pre class="literal-block"&gt;
nameserver 8.8.8.8
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="en-plus"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id11"&gt;En plus&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="//www.jujens.eu/posts/2015/Nov/08/rpi-wifi/"&gt;Se connecter en wifi à une raspberry pi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="sources"&gt;
&lt;h2&gt;&lt;a class="toc-backref" href="#id12"&gt;Sources&lt;/a&gt;&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fedoraproject.org/wiki/FirewallD"&gt;https://fedoraproject.org/wiki/FirewallD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://wiki.archlinux.fr/Partage_de_connexion"&gt;http://wiki.archlinux.fr/Partage_de_connexion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://gist.github.com/ChickenProp/3037292"&gt;https://gist.github.com/ChickenProp/3037292&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="Arduino - RPi - Robotique"></category><category term="Raspberry Pi"></category></entry><entry><title>Communication série facile avec python</title><link href="//www.jujens.eu/posts/2014/Jan/11/communication-serie-facile-python/" rel="alternate"></link><published>2014-01-11T00:00:00+01:00</published><updated>2014-05-09T16:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-01-11:/posts/2014/Jan/11/communication-serie-facile-python/</id><summary type="html">&lt;p&gt;Python permet de réaliser facilement une liaison via USB entre un PC et
une carte arduino. Nous allons l'illustrer par un exemple qui lit ce
qu'une Arduino Uno envoie et un autre qui envoie un nombre à la Arduino.
La diode de celle-ci doit alors clignoter du nombre envoyé.&lt;/p&gt;
&lt;p&gt;Il …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Python permet de réaliser facilement une liaison via USB entre un PC et
une carte arduino. Nous allons l'illustrer par un exemple qui lit ce
qu'une Arduino Uno envoie et un autre qui envoie un nombre à la Arduino.
La diode de celle-ci doit alors clignoter du nombre envoyé.&lt;/p&gt;
&lt;p&gt;Il faut uploader le code suivant sur votre carte Arduino :&lt;/p&gt;
&lt;pre class="code cpp literal-block"&gt;
&lt;span class="cp"&gt;#define LED_PIN 13
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledPin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Bonjour&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;C'est la carte Arduino qui parle&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledPin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledPin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour la lecture de ce qu'envoie la Arduino :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c1"&gt;# Module de lecture/ecriture du port série&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="c1"&gt;# Port série ttyACM0&lt;/span&gt;
&lt;span class="c1"&gt;# Vitesse de baud : 9600&lt;/span&gt;
&lt;span class="c1"&gt;# Timeout en lecture : 1 sec&lt;/span&gt;
&lt;span class="c1"&gt;# Timeout en écriture : 1 sec&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/dev/ttyACM0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writeTimeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ligne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="n"&gt;ligne&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Pour l'envoie de données vers la Arduino, &lt;em&gt;en python2&lt;/em&gt; :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="n"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;raw_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Entrez un nombre : &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Notez qu'il est possible d'envoyer un plusieurs nombres à la suite au
port série, puisque la fonction &amp;quot;serial.write()&amp;quot; en Python prend en
argument un tableau d'entiers.&lt;/p&gt;
&lt;p&gt;Pareil &lt;em&gt;en python3&lt;/em&gt; :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="n"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Entrez un nombre : &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ascii'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;La différence entre le code python2 et python3 vient du fait qu'en python3, les
communications réseaux et série doivent se faire avec des objets de type
&lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt; (chaîne d'octet). De même, les données reçues précédemment sont de
type &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt; en python3 mais de type &lt;tt class="docutils literal"&gt;str&lt;/tt&gt; (chaîne de caractère) en python2.
Voir par &lt;a class="reference external" href="http://python.developpez.com/cours/apprendre-python3/?page=page_12#L12-A-9"&gt;là&lt;/a&gt;
pour plus d'infos.&lt;/p&gt;
</content><category term="Arduino - RPi - Robotique"></category><category term="Python"></category><category term="Communication série"></category><category term="Arduino"></category><category term="Programmation"></category></entry><entry><title>Serial commincation made easy with Python</title><link href="//www.jujens.eu/posts/en/2014/Jan/11/communication-serie-facile-python/" rel="alternate"></link><published>2014-01-11T00:00:00+01:00</published><updated>2014-01-11T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2014-01-11:/posts/en/2014/Jan/11/communication-serie-facile-python/</id><summary type="html">&lt;p&gt;With Python, it is easy to communicate with USB from your computer to your
Arduino card. I'll illustrate this with a small example: the card will send some
text to the computer and then we are going to send a number, X, to the Arduino
whose LED will blink X …&lt;/p&gt;</summary><content type="html">&lt;p&gt;With Python, it is easy to communicate with USB from your computer to your
Arduino card. I'll illustrate this with a small example: the card will send some
text to the computer and then we are going to send a number, X, to the Arduino
whose LED will blink X times.&lt;/p&gt;
&lt;p&gt;Upload the code below to your Arduino card:&lt;/p&gt;
&lt;pre class="code cpp literal-block"&gt;
&lt;span class="cp"&gt;#define LED_PIN 13
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledPin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hi&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;I am your Arduino card&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lu&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledPin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HIGH&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;digitalWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ledPin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOW&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To read the data from the Arduino:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c1"&gt;# Module to read/write on a serial port&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;serial&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="c1"&gt;# Sereial port: ACM0&lt;/span&gt;
&lt;span class="c1"&gt;# Speed: 9600&lt;/span&gt;
&lt;span class="c1"&gt;# Read timeout: 1 sec&lt;/span&gt;
&lt;span class="c1"&gt;# Write timeout: 1 sec&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/dev/ttyACM0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baudrate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;9600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writeTimeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isOpen&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ligne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="n"&gt;ligne&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To send data to the Arduino, &lt;em&gt;in Python 2&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;raw_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Entrez un nombre : &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Note: it is possible to send one or more numbers in a row trough the serial port
since the function &lt;tt class="docutils literal"&gt;serial.write()&lt;/tt&gt; takes a list of ints.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;Python 3&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Entrez un nombre : &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port_serie&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ascii'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The difference between Python 2 and Python 3 comes from the fact that in Python
3, network and serial transfer must be done with &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt;. Likewise, the data
you receive are of type &lt;tt class="docutils literal"&gt;bytes&lt;/tt&gt; in Python 3 but of type &lt;tt class="docutils literal"&gt;str&lt;/tt&gt; in Python 2.&lt;/p&gt;
</content><category term="Arduino - RPi - Robotique"></category><category term="Python"></category><category term="Communication série"></category><category term="Arduino"></category><category term="Programmation"></category></entry><entry><title>Tutoriel d’utilisation basique de LibreOffice Writer</title><link href="//www.jujens.eu/posts/2013/Dec/02/tuto_LibreOffice_Writer_basique/" rel="alternate"></link><published>2013-12-02T00:00:00+01:00</published><updated>2013-12-02T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-12-02:/posts/2013/Dec/02/tuto_LibreOffice_Writer_basique/</id><summary type="html">
    &lt;p&gt;Vous pouvez télécharger la version odt &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_basique.odt"&gt;ici&lt;/a&gt; et la version pdf &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_basique.pdf"&gt;là&lt;/a&gt;.&lt;/p&gt;
&lt;h1 class="western" align="left"&gt;&lt;br&gt;&lt;br&gt;
&lt;/h1&gt;
&lt;ol type="I"&gt;
	&lt;li&gt;&lt;h1 class="titre-préface-1-western" style="page-break-before: always"&gt;&lt;a name="__RefHeading__2670_344518715"&gt;&lt;/a&gt;
	But de ce document&lt;/h1&gt;
&lt;/ol&gt;
&lt;p&gt;Vous pensez savoir utiliser LibreOffice (ou Word®) car c’est
facile et qu’apprendre à l’utiliser ne sert à rien&amp;nbsp;? Ce
n’est pas mon expérience. Elle prouve au contraire que la plupart …&lt;/p&gt;</summary><content type="html">
    &lt;p&gt;Vous pouvez télécharger la version odt &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_basique.odt"&gt;ici&lt;/a&gt; et la version pdf &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_basique.pdf"&gt;là&lt;/a&gt;.&lt;/p&gt;
&lt;h1 class="western" align="left"&gt;&lt;br&gt;&lt;br&gt;
&lt;/h1&gt;
&lt;ol type="I"&gt;
	&lt;li&gt;&lt;h1 class="titre-préface-1-western" style="page-break-before: always"&gt;&lt;a name="__RefHeading__2670_344518715"&gt;&lt;/a&gt;
	But de ce document&lt;/h1&gt;
&lt;/ol&gt;
&lt;p&gt;Vous pensez savoir utiliser LibreOffice (ou Word®) car c’est
facile et qu’apprendre à l’utiliser ne sert à rien&amp;nbsp;? Ce
n’est pas mon expérience. Elle prouve au contraire que la plupart
des utilisateurs n’utilisent pas cet outil comme il faut, alors
qu’il est très facile de gagner en efficacité avec quelques
notions de bases.&lt;/p&gt;
&lt;p&gt;En effet, lors de l’utilisation d’outils comme celui-ci
(qualifiés de WYSIWYG&lt;a class="sdfootnoteanc" name="sdfootnote1anc" href="#sdfootnote1sym"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;)
la tentation de mélanger contenu et forme est très vive. Par
exemple, lorsque vous écrivez un titre, élément de structure, vous
le mettez immédiatement en gros et en gras (forme). Ce faisant,
votre document n’est pas structuré pour l’ordinateur.&lt;/p&gt;
&lt;p&gt;Un autre exemple&amp;nbsp;: vous serez amené à rédiger des rapports
parfois très longs. Eh bien un document réalisé avec quelques
fonctionnalités très basiques peut vous être extrêmement utile&amp;nbsp;:
changer tous les titres en 2-3 clics, faire un sommaire automatique
avec renvoi, les titres qui se numérotent automatiquement…&lt;/p&gt;
&lt;p&gt;Pour la rédaction de longs rapports scientifiques contenant plein
de formules et plein d’autres choses, vous pouvez également vous
tourner vers LaTeX. Ce logiciel est conçu pour l’édition de
formules mathématiques et propose un rendu très professionnel pour
celles-ci ainsi que des symboles mathématiques très peu courants.
Il propose également des outils très puissants pour la
bibliographie&lt;a class="sdfootnoteanc" name="sdfootnote2anc" href="#sdfootnote2sym"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.
En outre, il vous force à structurer votre document.&lt;/p&gt;
&lt;p&gt;Ce document ne couvre que les fonctionnalités basiques (mais qui
vous éviterons de nombreuses frustrations par la suite). Un autre
document couvre des fonctionnalités plus avancées. Vous trouverez
plus d’informations en fin de document. Tout ce que vous lirez est
valable pour LibreOffice 3.6.x et 4.0.x.&lt;/p&gt;
&lt;ol type="I" start="2"&gt;
	&lt;li&gt;&lt;h1 class="titre-préface-1-western"&gt;&lt;a name="__RefHeading__2672_344518715"&gt;&lt;/a&gt;
	Mais pourquoi LibreOffice Writer et pas…&lt;/h1&gt;
&lt;/ol&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;h2 class="titre-préface-2-western"&gt;&lt;a name="__RefHeading__2674_344518715"&gt;&lt;/a&gt;
	Word&lt;/h2&gt;
&lt;/ol&gt;
&lt;p&gt;Word est un autre logiciel de traitement de texte édité par
Microsoft. Pendant longtemps il a fait la promotion de son propre
format qui fonctionne très difficilement avec les outils
concurrents. Le support de l’OpenDocument (qui est un standard) est
beaucoup plus récent. En outre, ce logiciel n’est ni
multiplateforme (comment on le fait marcher sous Linux&amp;nbsp;?), ni
gratuit. Vous pouvez vous procurer LibreOffice librement et le
distribuer à vos amis sans problème.&lt;/p&gt;
&lt;ol start="2"&gt;
	&lt;li&gt;&lt;h2 class="titre-préface-2-western"&gt;&lt;a name="__RefHeading__2676_344518715"&gt;&lt;/a&gt;
	OpenOffice.org&lt;/h2&gt;
&lt;/ol&gt;
&lt;p&gt;LibreOffice est en fait le descendant d’OpenOffice.org et est
basé sur le code d’OpenOffice.org. Vous trouverez plus de
précision sur Internet.&lt;/p&gt;
&lt;ol start="3"&gt;
	&lt;li&gt;&lt;h2 class="titre-préface-2-western"&gt;&lt;a name="__RefHeading__2678_344518715"&gt;&lt;/a&gt;
	Google Documents et affilié&lt;/h2&gt;
&lt;/ol&gt;
&lt;p&gt;Bien que Google Documents puisse être utile pour le travail
collaboratif, il est toujours très loin d’être complet. Je dirais
même qu’il lui manque de nombreuses fonctions essentielles
présentées dans ce document. De plus, vous perdez le contrôle sur
vos données et vous êtes tributaires de Google (et de votre
connexion à Internet).&lt;/p&gt;
&lt;div id="Table of Contents1" dir="ltr"&gt;
	&lt;div id="Table des matières1_Head" dir="ltr"&gt;
		&lt;p align="left" style="margin-bottom: 0mm; page-break-before: always; page-break-after: avoid"&gt;
		&lt;font face="Liberation Sans, sans-serif"&gt;&lt;font size="4" style="font-size: 16pt"&gt;&lt;b&gt;Sommaire&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;/div&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__957_142577672"&gt;1 Structurer un document&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="text-indent: 10mm; margin-bottom: 0mm; background: transparent"&gt;
	&lt;a href="#__RefHeading__959_142577672"&gt;1.1 Les titres&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="text-indent: 10mm; margin-bottom: 0mm; background: transparent"&gt;
	&lt;a href="#__RefHeading__1270_142577672"&gt;1.2 Numéroter ses titres&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1272_142577672"&gt;2 Insérer des images&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__965_142577672"&gt;3 Les numéros de page&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__967_142577672"&gt;4 Rupture de page&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__13831_757466230"&gt;5 Faire une page de garde&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__3212_976366088"&gt;6 Le sommaire automatique&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__969_142577672"&gt;7 La correction
	orthographique et grammaticale&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="text-indent: 10mm; margin-bottom: 0mm; background: transparent"&gt;
	&lt;a href="#__RefHeading__13984_757466230"&gt;7.1 La correction
	orthographique&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="text-indent: 10mm; margin-bottom: 0mm; background: transparent"&gt;
	&lt;a href="#__RefHeading__13986_757466230"&gt;7.2 La correction
	grammaticale&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__3214_976366088"&gt;8 Divers&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="text-indent: 10mm; margin-bottom: 0mm; background: transparent"&gt;
	&lt;a href="#__RefHeading__3216_976366088"&gt;8.1 Puces et numérotation&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="text-indent: 10mm; margin-bottom: 0mm; background: transparent"&gt;
	&lt;a href="#__RefHeading__3218_976366088"&gt;8.2 Les divers collages&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__993_142577672"&gt;9 Citations&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; text-indent: -4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__13988_757466230"&gt;10 Auteur et licences&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h1 class="western" style="page-break-before: always"&gt;&lt;a name="__RefHeading__957_142577672"&gt;&lt;/a&gt;
1 Structurer un document&lt;/h1&gt;
&lt;p&gt;Structurer votre document c’est ce qui vous permet de faire la
différence entre les titres, le corps de texte… Vous allez me dire
en sélectionnant du texte et en le mettant en gras et en gros, j’ai
fait un titre. Eh bien non. Vous avez structuré le document pour
l’impression, pas pour l’édition informatique. L’idée de la
structure c’est de «&amp;nbsp;dire&amp;nbsp;» à votre ordinateur que ce
texte sélectionné est un titre. Il pourra alors le manipuler comme
tel et le mettre dans un sommaire, vous proposer des options de
navigation entre vos titres…&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__959_142577672"&gt;&lt;/a&gt;1.1 Les
titres&lt;/h2&gt;
&lt;p&gt;Comment faire un vrai titre me direz-vous. Rien de plus simple.
Cliquez sur la flèche à droite de &lt;i&gt;Corps de texte&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
puis sélectionne&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;i&gt;T&lt;/i&gt;&lt;i&gt;itre &lt;/i&gt;&lt;i&gt;principal&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
&lt;/span&gt;&lt;span style="font-style: normal"&gt;Si ce titre n’apparaît pas
dans la liste, sélectionnez &lt;/span&gt;&lt;i&gt;Corps de texte &lt;/i&gt;&lt;span style="font-style: normal"&gt;et
tapez &lt;/span&gt;&lt;i&gt;Titre principal&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;N&lt;img src="data:image/png;base64,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" name="images1" align="left" width="643" height="84" border="0"&gt;&lt;br clear="left"&gt;B&amp;nbsp;:
le &lt;/span&gt;&lt;i&gt;Titre principal&lt;/i&gt;&lt;span style="font-style: normal"&gt; est
suivi du style &lt;/span&gt;&lt;i&gt;Sous titre&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Voilà, vous venez de donner un titre à votre document. Vous
pouvez également mettre un titre à vos sections/chapitres en
sélectionnant &lt;i&gt;Titre 1&lt;/i&gt;&lt;span style="font-style: normal"&gt; pour
le premier niveau puis &lt;/span&gt;&lt;i&gt;Titre 2&lt;/i&gt;&lt;span style="font-style: normal"&gt;
pour le second niveau et ainsi de suite.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;b&gt;Titre&lt;/b&gt;&lt;/i&gt;&lt;span style="font-style: normal"&gt;&lt;b&gt; est une
sorte de super-titre. En le modifiant, vous appliquez des
modifications à tous les titres&amp;nbsp;!&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Et maintenant, modifions tous nos
titres sans en oublie&lt;/span&gt;&lt;span style="font-style: normal"&gt;r&lt;/span&gt;&lt;span style="font-style: normal"&gt;
un&amp;nbsp;! Cliquez sur &lt;/span&gt;&lt;i&gt;Styles et formatage&lt;/i&gt;&lt;span style="font-style: normal"&gt;
en haut à gauche de l’écran.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images2" align="left" width="643" height="84" border="0"&gt;&lt;br clear="left"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p style="font-style: normal"&gt;Puis faites un clic droit sur l’élément
que vous voulez modifier et cliquez sur &lt;i&gt;modifier&lt;/i&gt; (ici &lt;i&gt;Titre
&lt;/i&gt;&lt;i&gt;principal&lt;/i&gt;).&lt;/p&gt;
&lt;p&gt;Vous pouvez alors choisir en navigant dans les différents onglets
l’alignement du texte (centré, justifié, aligné à droite,
aligné à gauche), la police, la taille, la fonte, la couleur… Une
fois que les réglages vous conviennent, appuyez sur OK pour les
appliquer. Voilà, plus besoin de parcourir tout le document pour
changer les titres. De plus, un titre suivit par un texte ne sera
jamais seul sur une page.&lt;/p&gt;
&lt;p&gt;Vous pouvez également ajouter vos propres styles en faisant un
clic droit dans cette fenêtre et en choisissant &lt;i&gt;Nouveau&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ne modifie&lt;/b&gt;&lt;b&gt;z&lt;/b&gt;&lt;b&gt; jamais au grand jamais l’apparence
des éléments de structure via la ba&lt;/b&gt;&lt;b&gt;rr&lt;/b&gt;&lt;b&gt;e de formatage.
Vous &lt;/b&gt;&lt;b&gt;encourrez&lt;/b&gt;&lt;b&gt; des problèmes à traiter à la main.&lt;/b&gt;&lt;/p&gt;
&lt;p style="font-weight: normal"&gt;Vous pouvez naviguer entre vos titres
via le menu de navigation. Pour cela, allez dans &lt;i&gt;Affichage &amp;gt;
Navigateur&lt;/i&gt;&lt;span style="font-style: normal"&gt; ou appuyez sur F5.
Vous pouvez aussi naviguer entre vos images, index…&lt;/span&gt;&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__1270_142577672"&gt;&lt;/a&gt;1.2 Numéroter
ses titres&lt;/h2&gt;
&lt;p&gt;Un autre intérêt à faire des titres de section c’est que
LibreOffice peut gérer leur numérotation tout seul. Et si vous
ajoutez un titre entre deux autres, ils seront renumérotés
automatiquement&amp;nbsp;! Comment fait-on&amp;nbsp;? Allez dans la barre
d’outils, sélectionnez &lt;i&gt;Outils&lt;/i&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;span style="font-style: normal"&gt;&amp;gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;i&gt;Numérotation des chapitres&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Dans la fenêtre qui s’ouvre, sélectionnez le type de numéro
que vous voulez pour chaque hauteur de titre. Le champ &lt;i&gt;afficher
les niveaux&lt;/i&gt; permet de faire des plans de ce type 1., 1.1,…
Appuyez sur OK pour valider les changements. Vos titres se numérotent
sans votre aide&amp;nbsp;!&lt;/p&gt;
&lt;p&gt;L&lt;img src="data:image/png;base64,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" name="images4" align="left" width="643" height="534" border="0"&gt;&lt;br clear="left"&gt;es
champs &lt;i&gt;Devant&lt;/i&gt; et &lt;i&gt;Derrière&lt;/i&gt; vous permettent d’ajouter
ce que vous voulez avant et après vos numéros de titres. Si vous
voulez entourer les numéros de vos titres par &lt;i&gt;Salut&lt;/i&gt; et &lt;i&gt;Adieu&lt;/i&gt;,
c’est ici que ça ce passe. Je vous conseille de mettre un espace
dans &lt;i&gt;Derrière&lt;/i&gt; (vous comprendrez en lisant la section sur le
sommaire automatique).&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__1272_142577672"&gt;&lt;/a&gt;2 Insérer
des images&lt;/h1&gt;
&lt;p&gt;Vous pouvez insérer des images à partir d’un fichier via le
menu &lt;i&gt;Insertion &amp;gt; Image &amp;gt; À partir d’un fichier&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Lorsque vous sélectionne&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
cette image, vous pouvez choisir l&lt;/span&gt;&lt;span style="font-style: normal"&gt;’adaptation&lt;/span&gt;&lt;span style="font-style: normal"&gt;
de cette image. &lt;/span&gt;&lt;span style="font-style: normal"&gt;Des options
supplémentaires sont disponibles sous l’onglet &lt;/span&gt;&lt;i&gt;Adaptation
du &lt;/i&gt;&lt;span style="font-style: normal"&gt;texte. &lt;/span&gt;&lt;span style="font-style: normal"&gt;Fiez-vous
au dessin, ils sont très parlant&lt;/span&gt;&lt;span style="font-style: normal"&gt;s&lt;/span&gt;&lt;span style="font-style: normal"&gt;.
Vous pouvez également modifier le style &lt;/span&gt;&lt;i&gt;Images&lt;/i&gt;&lt;span style="font-style: normal"&gt;
via &lt;/span&gt;&lt;i&gt;Styles et formatage&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
&lt;/span&gt;&lt;span style="font-style: normal"&gt;Ce faisant, vous pouvez
mettre toutes vos images avec la même adaptation.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;En double cliquant sur une image, une
boîte de dialogue s’ouvre. Elle vous permet notamment de rogner
l’image, de choisir la bordure et la couleur de fond.&lt;/p&gt;
&lt;p style="font-style: normal"&gt;Dans l’onglet &lt;i&gt;T&lt;/i&gt;&lt;i&gt;ype&lt;/i&gt; de
la boîte de dialogue vous pouvez choisir l’ancrage de votre image.
Vous avez quatre types d’ancrage possible&amp;nbsp;: &lt;i&gt;à la page&lt;/i&gt;,
&lt;i&gt;au paragraphe&lt;/i&gt;, &lt;i&gt;au caractère&lt;/i&gt; et &lt;i&gt;comme caractère&lt;/i&gt;.
Cela vous permet de savoir par rapport à quoi le positionnement de
l’image sera fait. Par exemple, si l’image est ancrée à la page
et que vous sélectionnez un positionnement vertical &lt;i&gt;Haut&lt;/i&gt; et
horizontal &lt;i&gt;Centré&lt;/i&gt;, votre image sera toujours en haut de la
page et centrée horizontalement.&lt;/p&gt;
&lt;p style="font-style: normal"&gt;Le gros avantage de l’ancrage &lt;i&gt;comme
caractère &lt;/i&gt;est que l’image se comportera comme un caractère et
restera donc là où vous l’avez placé.&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images11" align="bottom" width="643" height="532" border="0"&gt;Afin
de réduire la taille de votre document, je vous invite à rogner vos
images en dehors de LibreOffice avec un logiciel de manipulation
d’images tel que Gimp. En effet, lorsque vous rognez une image,
LibreOffice conserve l’image de départ dans le fichier. Ainsi,
votre fichier odt va grossir très rapidement avec des informations
inutiles. Il en est de même pour le pdf généré à partir de ce
fichier.&lt;/p&gt;
&lt;p style="font-style: normal"&gt;Si vous rognez vos images, ces fichiers
seront plus petits et donc, par exemple, pourront être envoyés plus
facilement par courriel. Vous pourrez alors exporter le pdf sans
compression pour avoir un maximum de qualité, sans avoir un fichier
trop gros. De plus, ces logiciels étant dédiés au traitement
d’images, il est souvent plus facile de redimensionner correctement
celles-ci.&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__965_142577672"&gt;&lt;/a&gt;3 Les
numéros de page&lt;/h1&gt;
&lt;p&gt;Vous pouvez numéroter vos pages en&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;Insérant un pied de page&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Y insérant un numéro de page&lt;/p&gt;
&lt;/ul&gt;
&lt;p&gt;Pour insérer le pied de page, cliquez simplement en base de la
page. Une boîte comme ci-dessous apparaît. Cliquez dessus pour
ajouter le pied de page.&lt;/p&gt;
&lt;p&gt;&lt;img src="data:image/png;base64,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" name="images7" align="left" width="191" height="28" border="0"&gt;&lt;br clear="left"&gt;NB&amp;nbsp;:
cela fonctionne aussi pour les entêtes.&lt;/p&gt;
&lt;p&gt;Pour ajouter le numéro, allez dans la barre d’outils, puis dans
&lt;i&gt;Champs &amp;gt; Numéro de page&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Pour que vos pages aient des numéros de la forme&amp;nbsp;: &lt;i&gt;numéro
de la page/nombre de page&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
ajoute&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
le caractère '/' après le numéro de la page &lt;/span&gt;&lt;span style="font-style: normal"&gt;puis&lt;/span&gt;&lt;span style="font-style: normal"&gt;
insére&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
le champ &lt;/span&gt;&lt;i&gt;Nombre de pages&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__967_142577672"&gt;&lt;/a&gt;4 Rupture
de page&lt;/h1&gt;
&lt;p&gt;Si vous désirez qu’un texte commence toujours sur une nouvelle
page, par exemple le texte qui suit la page de garde ou le sommaire,
il faut insérer un saut de page avant ce texte. Allez dans &lt;i&gt;Ins&lt;/i&gt;&lt;i&gt;e&lt;/i&gt;&lt;i&gt;r&lt;/i&gt;&lt;i&gt;tion&lt;/i&gt;&lt;i&gt;
&amp;gt; Saut manuel…&lt;/i&gt;&lt;span style="font-style: normal"&gt; Vous pouvez
également insérer des sauts de paragraphes et de colonnes.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAbwAAAE9CAIAAAD/PkD1AABA1ElEQVR4nO2dB1xT59fHw8gmEEYgYYiCIqDiRq2L6cDdam2ddW/F2aptHX21jjoqDlTcs9a2/1aLExARq3ZYN+JWNrJkhEzeE65N05DEJMBNouf7yQfufeZ5bu795ZznLtsrV67cu3evdevWPj4+HA6HgiAIgqhQWlr6+PHj69evBwQEMJlMW1DMwYMHs9nsqqoquVxuavMQBEHMC5DHoKAgcCt/+OGH3679btuqVStCMU1tGIIgiJkCCgk62bJly+SUS7Z+fn7oYCIIgryRxo0bv9exgy2LxZLJZKY2BkEQxNwBtVTMaYKbibE5giCIPtjY2NiiYiIIguiPQjRRNxEEQfQERRNBEMQAMDxH6ob0Bw/WrN+4cvlSVx7P1LYgSD2CovmuM2TYiGfPn1+7dLE2jZyIP7Xmm3UUK6v76ek8F5e6ss3cEAqFcLiwWExTG4KYEoVoWllZmdoMxGTU/ttfvW79Dz/9r4GX1/o1qxt6N3iLL/sdNW5C7X9gEEtHccmRtbW1qc1ATExtAo7mzZqVlpYuWbyISqW+3df8Ej8wGJy942B4jvxLh67dOwS3B+FLu58Oq21bt1q0YD6Xy4Xl7JycHbt2X//7RkFhoSOX27xZ4MrlyyBdIpEUFhamP3gY3rsPOJtjRo0MC+lONKXa8vEjh1gs1o643ZevXCmvqIDqc2fN9G7QQGNJL09PVZOg2LFDB2qu6rBWFY2Ww26/YvWahw8fvcjMtLayauzrO33K5GaBATp67NGnX8mrV0qDZ8+c8dGQwXW15RELAs+eIwqU+8DVa78L+Pw2rVs9ePAwOeWSk5PTp3PnQPrcTxc+efp01PBhPj6NcrJzBAIBUSV2Z9zBI0fDQ0NHDvv419OnF37xZWzMplYtgyCLzWKFh4XSqFRHR0d3gWDC1GmgbuM+Gc1msw8eOTJlxqzvDx8i5gdVS4Jiqu2Q4N+ppqiuarNWFW2Wu7m6ujg7D/X2zs7O3r1v//yFi078eJyIujT2OHL4sAOHDoNuThg7hqLwrwPxwHk3QU8T+Q/gVf18/JhcLs/Ny+vdf+Dde2lEekVFBaVaW319fHr36AHL4OJBsZ9+/oXJZH615AsajRYZHtYtosf/TpwkRJPH4y39fDGxg926fefO3XugrZPGj4MU8Pi+XP7VpcuXe0SEq5UE17X21qqi0XL4O2XiBPhLTE/du3//YsqllwUFOk79fzJyxMn4UyCakyeMVw5ff1ORtwb0NBEFyn0AvCqhUAgLXAcH+CsSiYisdatXbYiJ2XfwEHwCAwJmTZsS1KJFUXFxebUkvRcSpmwqJzdH2RpUJxYyszLhb0JSUttOnZUlc3Nza5bUbZ6e1qqi0XLQu70HDp49nwDBO9Qi5A90UFm9Zo9KNReLxTpMRd56UDQRBar7gEaF8mnUcPvmmKzs7AvJF7/dsnXRl0shmHWwt6fTaLZU6pkTPyufYA3SU1lZqdYUxMLwN6Rb12/XfaNsGdRHqUTadkJwYPNfvpRKpTY2NhoVTZueKtFo+c1bt2N3xkWGh+/cupnNZn+zYePxn/5HHAtv7BFEFspo25LIWw+G54heLPziSy6XG9C06avSUhAUl+qLMSGw/ejDIeDBjR4/YUDfvgwG4/mLF1G9ejX0bqBWvVlgYLOAgAsXU2bP/7RjcHtQ1ezc3BlTJr+x32aBAdf/vvHJhIkguxBE15XllOrrrNLu3z9z7nyFUAiG6dOji4vz02fPYAgtmjdr1TKoY3CwEfYglg56moiCN/purq6ul1Ivn/g13pHLjQgLnTF1CpE+bfIkZ2fnU2fObN2xk0ajOjs5R4aH1XTQYGHrpm9jtm699sefKamp9vb23l5eOjpV8vlnn/7fqtVp99NLSl517tTpydNn5eXlBnmaGi1v3bIltLz/0OENMZudHB2bNPZ9WVBAVNfRY/SM6V+vXgtKCn4rlUrt0L69QRsZeTuwxcnsd5yfjh0Fh7GsrAyWb/x+FfYH4syJ2ur82dGfzZsLJUE+IACHyJrYcyC+/mjI4JHDPiayAPAiIUutKYBKtf1s/jyIeYmSkEtMR9YsqYq7QLArdhtxUhv6JRaIwjqsVUWj5bDQv2+fDwYNVBoDhkFdWNDRo2+jRgf37iaqwMBxcvPdBD3Ndx1wo5TLpaWlqlmqq8ppypqIq1FLVGuKUu3EaWykZklVQLa06akOa1XRZrlGs3X3CFmqmwt5N8E5TQRBEANATxNBEMQAUDQRBEEMAMNzBEEQA0BPE0EQxABsmUx8oiqCIIi+YHiOIAhiALamNgBBEMSSQE8TQRDEANDTRBAEMQAUTQRBEANA0UQQBDEAFE0EQRADQNFEEAQxABRNBEEQA0DRRBAEMQAUTQRBEANA0UQQBDEAFE0EQRADQNFEEAQxABRNBEEQA0DRRBAEMQAUTQRBEAMwRjS3x+36/sefaqbPmj6tX1TvWpuEIAhivhgjmiOHfTzkg/dhITMza/aCT48dOkCks1msujQNQRDE/DBGNFnVwEJ5WTn8dXJ0rGOjEOTtQi6XP3zysKikSCqRmtoWhGJLtXV0cGzcqLG1tbUx1evQlMPfHbt7L+3/ln5JrN6+c3fF6jWH9u4Gy/oM+iAiLDQlNVUmk3fu1DF6+jQajUYUk0qlO/fsTb6YIpaIg9u1mzZpIofDqUOrEMTkgGJKJJLgNsHOTs6mtgWhFBQW3E27C1+Kn6+fEdXrUjR7RIQfOHykuLiYy+XC6tmEhMjwMELLRSJR88DAiWPH5OTmrd+0acOmzZ/Om0PUituz9/799CWLFzKZzC2xO7bH7Zo3O1q12atXr9ahkQhSSzp06GBoFfAxUTHNB/giAv0Dr/11zbjqdSmaLs7O7dq0TriQ/MHAASKxODnl0paN65W5/n5+bDbb16dR9PTp0fPmz5s9y8bGBsKWE/Gn1q5c4ebmBmUGDegHeqrWrBH7KIKYFRCVw4GK7+MyH+DrMHqqpI4vOYrq1WvfwUMgmr9duerdwMvTw6NmGUgFSS0sKuK5uBQUFIITOnPuvLo1A0HMjapqTG0FUgfUsWgGt2u7IWbzk6dPz55P6BEerrHM02fPaTSas5MTLHM4dlZWVvvidrgLBHVrCYKYD7CTm9oERB2jv5Q6Fk2IuHtFRnx3/Iebt28v+nS+ataDR4+cnBzz8vO/3bJlYP9+xFwng8Ho3KnjV1+vGjd6NLilFUJhbl5epw7BdWsVgpgD6GmaD7X5Gav7O4J69+wxcuz4kG5d7dhs1fSVa9bCX1ceLzIifMRHQ5Xpc6Nn7TtwcP2mmOKSEgGf7+XliaKJvGVYURSHKIqmWUF8KUZQK9EEgTsff1Itke/m5uLs3CNCPTbfsz0WytdshGNnN33KZPjUxhIEMWuscE7TvFB8F8b6mnXvad66fUdeVdW2des6bxlBLBT0NM0Q03iaGvn55K8RYaE2NjZ13jKCWC6omGZFbb6OOhbN0tLSu/fujRz2cd02iyCWDZ48N0PMJDzncDhH9u+tmV5z6hNB3jUsy9ksKChYuXLliRMncnNzBQJB//79P/vsM6fqKwUp1de93Lhxo2nTprAsFAp79+7t6Oh47NgxKpVqUqvJAJ+niSD1jhXFyrJOBL18+bJLly7u7u7ffvutr6/vw4cP16xZAykpKSlK3SRGJJPJRo0aJZfLDxw4YGtrayljBDvNaE4TQRB1LO3s+RdffMHn8+Pj4+l0Oqw2btw4NDQ0MjIS0jdvfn2jMwwHtHLOnDnp6ekJCQksFsuCBmheZ88RBFHDsjxNqVR6/Pjxw4cP02g0pc2w/Pnnn48cOXLjxo3K07zr1q07efJkYmIixOaWMjoC9DQRBKkz8vLyysrKgoPV7zHp0KFDaWkp5Aqqb3o+duzYN998c/nyZS8vL1OYaTJQNBGk3rGysiRPE4JuiqYnjBCrynQ/Pz9wP3/88ceAgACT2FkbFJ6mmdx7jiCIRixINF1dXdls9u+//x4aGqqafvXqVTs7Ox6PRwwkKCgIQvjBgweDpwlhu4mMNRIzuk4TQZCaWNacpo2NzaBBg1auXNm5c2flJUQikQhShgwZYm1trXQ5QVW3bt06depUCNjDtTzVzDzBOU0EMW8s7eL2pUuXhoSE9OnTZ/78+T4+Po8fP16zZk1+fv6SJUvUSg4dOjQ7O3vEiBFnzpwB39Mk1hoJnj1HEHPGgjxNAGLwpKQkEMpZs2bl5eW5ubn17dt3wYIFqmfJlSOaOXNmRkYGxOkJCQmenhoeymOGYHiOIGaN0ZGgCXF1df2mGo25JSUlymUrK6u11ZBlWt2A4TmCmDGWdnH7W4/lXdwukYjTHt7OK8x5WZgHqy5Orq5OfP/GzalUmknsQZD6Ri6XW4poQgyuu0BRURE5ltQfxGVVxmEC0cx9mX3lr4uO9s4ujm7urg3gV1gsqSwqKYxP+qljm25uLviyIORtw7LOnhcWFuouYCkD0YElnT3PL8j5/e/UwCYt7NlcOoNBpSoMkEqllZWCV2UlkNWhdReeM59kqxCkfsHw3MywmPBcKpXcuPtHC//WjlxnFoulTKfTKWy2HYvFplFpUCCkU09bW8t4wNRf1/8+c/78/NnRtrY4O4xohfA0TW0F8i8W42k+y3zs4sx3duKx//vONQI7Oztra+uiV0VQzNe7ac0CEVF9/y3MZge1aB49fZryQVX1x4sXGWMmTdb4SNDAAP+fT578fNnyJYsWMZkMtVwwWNubkTSiWl5Hp4glgp6mWWExlxyVVZTyeXzwKG1sNPfLZLKgQO7LHG0tbFiz2sPDXSKRPHz0eMeu3Zu2blv6+eJ6s/c17u6CY4cOaMxiMBhgwM49e3/8+efhKq/YrNdOEYsD33tuhljGvefCygoHjhOdRtdmro21jYO909OMx9pa4Do4OFWf2nNzdWUw6MtWfF1ftqpaZWPjpP18Ioxl4tgxtTkZZ0SniGVBp9NLS0tVp6QQ0wJfB/GoUCMgVTSpVBqVSgU50Caa4DNTFeh14RHoFDh6xLJUKgV3L/liilgiDm7XbtqkiRwOB9L7vj84Miz075u3cvPyQHAnjB0T2r3boaNHL1+5umXjBqLu3gMH09LTV321vEIojN0Zd+Xa71VyeccOwZPHjyOmEbRFyqvXrX/w8FFmVpYrjzd14oQOwe11G2xQedVOYbMc/u67+NNnYRRELhHFaxydjq2BmAo3V7fM7EwPgYfGiSmEZMrLy+HrgC/FuOqkiqazo4tEJra2trG2ttZYAHRQIhVDMW0tFJeUsNksmVwO4fmW2O3hId2J9Lg9e+/fT1+yeCGTydwSu2N73K55s6MhvbKy0pZKBdWAaPd8YtI3Gza+16ljZHj43gOHMjIzPT08QI/OJyWN/+QTKByzdVtBYeGOzZtgecWatTHbYj+bN1fHcNq3bTOofz/o8cz5hOVfr/rl+DHd7+A0tLwSUMzTZ8/Pmj7VXSB48vSp0r/WODo6jaZtayCmAo5PmVz29NlTqUxqalsQiq2NrRvfDb4UiURiTPU6N0gHDnbcsrJSNxeBVtG0kkMBKKathdkLPiUWWExm/359PxkxnFIttSfiT61ducLNTfHTMWhAvw2bNiur9I+KIk6tDB0yeP+hw/n5+aCVrVu1TEi6MHrE8LtpaWWlZe917ACbD3Rnx5YYLlfR+5QJEyZNnzEvepaO0+JhISHEwvsD+h899j24e+4CXReZGlpeyU+/nJw/Oxp8RlgG41Wzao4O2tSxNRCTAHuXl4eXbyNfnNw0B8BVEovF4HMYV51U0eQ58x8+u1chLOPYOWjce8rKX5ULSxt7B0CAqbEFIixNSU1d9c36nuHhhKIVFBSKRKKZc+fp7h1cMPhbJVecNesZEQFR+ajhw0AoQ0O602i0nNxc2JQe7u5EYQ8Pd1gtLCqCUFpja5ALDuPxH3/Ky8uDuB5SZFKZjt4NLa9EJBYXFxd7uL9BXpWj03NrICRTWY2prUDqAFJFUyaTNfRs/OTFY58GjTl29mq5pWWvIAsKQDHd7XTt3Pn6jZsr166NWb8OdJPDsQMJ3he3Q0/HDejyXqdvt2y9dfvOhYspq75aDilOjo7QSGZWVqOGDWE1KysL3GEdp2Ju3Lq1JTZ2yaJFzZsFUqnUnv0GaCxWRakyrrwSGpUKbvXde2lqPqY2jNgaCILoD6miCd6WjY1tA/eGmdnP7dj29hwHBoNJUfwIC1+VloCbCVnWVjZvFE1g8vhx02fPAW9x/JhPGAxG504dv/p61bjRo0FZwI+DyLdTB/U3nKhCp9NDunUF3QRZ9GvSmFL93ihI2bpj56IF82F12864HhHhOmLzsrJyK4oV1MrOyTmXkKixDIfDuZt2HxYaeHkZWl6ZCArYr0/U5tjtILWNfX0ePX6ie8sYsTUQBNEfsu9jAUG0sbHx9vQtKinIL8gTixUBC43GYDKYkCgWi/VRzOoqtC8WfjZt1uz2bdu2DGoxN3rWvgMH12+KKS4pEfD5EMK/USZ6RUbGnz4zcdxY5UTBrOnTtm7fMX7KNBtra9CdiePG6agO7YeHhny+dBmNTofCPBcNJ68G9e8Xs3Vb88DA1Su+MrS8ajr8MIB879l/oLS0tFGjhrrHBRixNRAE0RMT3PwHslhZWWlvx3V0cCZOH8uqgUTdl+mrXfTj5en5yw/fE8scO7vpUybDR3cV1dXAAH+1XDs2e8Gc2TX7BdGpeb0RWA4iCx8dBo8aPgw+xpVX7RRkfcyokfCBZfhdiRr4Po1O0zE6bVsDQZDaY5o7pomzVybp2tK5c+8e6K+Ls7OpDUGQdxSLecyE6o3narz1N2hLpdJXpaUyqezRk8ebY7cP7NdXzws8EQSpcyxGNN96ZdRB+oOH6zfFZGVnu/J4vSIjPxoy2NQWIci7i8WI5rtMYIB/3LYtprYCQRAFKJoIUu9UVVXl5udm52RXCCtMbQtCYTFZAr7Ajedm3A1aKJoIUu+AYhYUFgQ1D3J2wjN4pge+i7T0NFjguxrzkggUTQSpd8DHBMV0sHfAi0bMAfgi/P38b96+iaKJIGYKROXgY4pEIlMbgiiQyWTwdRg9VYKiiSBkgK+7MCss5nUXCPJuQpxwQNE0KyzjdRcI8s6CnqZZgZ4mgpg1xCt8UTTNB4t5hS+CvKNYKY7SOn/7HmI0ih8wYx+ij6KJIPUOeprmBnqaCGIBoGi+HZhGNCUScdrD23mFOS8LFe+kdXFydXXi+zdurufLexHEwsDXqZkhFhSe577MvvLXRUd7ZxdHN3fXBmC7WFJZVFIYn/RTxzbd3FzwzTbIW4g5hOfX/74xf9Hi0SOGjxz2cZ03HhHVl3jvYZ23XB9Y0tnz/IKc3/9ODWzSwp7NpTMYVKrCAKlUWlkpeFVWAlkdWnfhORtzbxOCmC1mMqd5LiGxdauW5xOThn80tD5eJlxFMf0Y9cRi5jSlUsmNu3+08G/tyHVmsVjKdDqdwmbbsVhsGpUGBUI69bS1pZJpmA6uXLvWskUQk8kwtSGIJWNFkcvlphUUkUh0+cqV7Vtips6Mvpd2P8C/aZ13YQ4/DHqiuJLBIsLzZ5mPXZz5zk48NptdM9fOzs7a2rroVREU8/XW8I3C93H67Dn4ZGRlVVZWenp4tG4ZNHnC+Hq1+fOly+s16LCsoAYxDnPwNFN/uxLg7+/i7Ny9W1dwNv2b+hHpA4YMDQ8NuXHzVl5+PtfBYdwno0O6ddWR3rPfgLhtW7w8FXvsi4yM8VOmnTnxM9GU6hghfNy1d9/FS6lisbh9u7ZTJkzgcOwgvf/gDwf263vm3PnikhJlRfKxGE+zrKKUz+ODR2ljo7lfJpMFBXJf5mjM3R636/qNm32jens38LLncCiKN4hxjDAjJyd38dJlu2K3GlEXQYzD5KKZkJQUERYKNoSHhHyxbPmk8WOJN1SD/wELUyaMd3cXJCRdWPftpk4dgmk0mrZ01bGo/qX8d4y79u2/n/7g888WMBjM2J1xO3bvnjNzBqXa4YUoc+3XKygmvZzAYuY0hZUVDhwnOo2ubT7FxtrGwd7pacZjjblnExK+XLSwVVBQLc2QSCTPnj+vZSMIoj+ww5v24vbi4uLbd+9NmTihoKDQ2dmJzqBf++PPjsHtidyonj29PD1gYfCggQePHM3Ny/Nwd9eRLpe/HgssUIhQtxqVdPmvp06vXL6U58KD1f59ojZti1UW6xgc/E87JtsgCk/TIu49p1JpVCrVxsZGm7kwEqoCzRce+fs13bZjJ8TjoJtqLaxet/7Bw0eZWVmuPN7UiRM6VO8NqpHvixcZYyZNPh9/Min54orVayj/vKnts3lz4edXtSmIJg59d+x8QiLsImoGQMSxc8/e5IspYok4uF27aZMmcjjqri5UP3D4CEQlRUVFEA0tnD+Xy+VWCIXwY3vl2u+wT3XsEDx5/DiNExQUxTPEtJbs+/7gyLDQv2/eAsMgXJowdkxo92460vWxFiEN085pXriYIhQKx06aokxJvHChQ/t2/6y99hDh2KP8x9Q3pCvO/fzHa3ud/rKgADzKuZ8uVLWhZjETUhu9JlU0nR1dJDKxtbWNtbW1xgIwEolUDMU05oIAbdsZt3jJMkcut3/fPlE9eyhVoH3bNoP692MymWfOJyz/etUvx49pe19jSLeujRp6KydialoCYcUff/41Z9YMvhs/IzNz8ZKlyqy4PXvv309fsnghdLQldsf2uF3zZkerVQdZT0tPnzVtqpenp42tjYODAyTGbN1WUFi4Y/MmWF6xZm3MtlgQa43m6SipCJeoVNA+CJfOJyZ9s2Hje5060okwSlO6PtYi5GDyOc2EC8nLvljctnVrYvVFRsbMufPLysqIn2Q121Sj75rp4K+AZ6AxPFeqqh3bDort2BIj4PNVq6u1b0IsZk7TwY5bVlbq5iLQKppWcigAxTTmgkQumDMbQoyUS6mgDvsPHV4wJ7p7V8XkdFhICFHm/QH9jx77Hnwud4Hm6z3hu7SxVuipRlWVyWQ/nzj57Tdrm/o1gVUP938bgR3iRPyptStXuLm5weqgAf02bNqsVh2cu/gzZ2Ff8W7QQJkokUjAWkgElxNWp0yYMGn6jHnRs4gZJVXeWLJ/VBThOA8dMhiGn5+f7+nhoTEdhv9GaxHysDLl/N3zFxl5+fktVea14Bcd9pxLl3/rGRlhaGuwa52MPzX4/UHQ5rXf/1Smc+zs7qc/IBpnMOgQg6/6Zv3oEcM8BO7CSmFeXn7wv46t6bGYe895zvyHz+5VCMs4dg4aI/Sy8lflwtLG3gGgPtoage8mqlfP3j17HDxyNHbnLhBNGD84mMd//CkvLw/CWygjk8qMsxC8POi6YUNvDVkFhRBxzJw7T0d12I1Adon5GtU2wUJlooeHO6wWFhW58ng1e9ezJJ2Yj5erH4fKdH2sRcjEhO5VUnJy504dIb5TNaBbl86JF5J7RITXtE23pzl98qTNsduTL6X6NGrYpHFjBp1OlOnXJwoCwQD/pl99+QWszpw65dDRozFbY0tKStz4bl4eHu3btVVr34RYzIkgEJSGno2fvHjs06Axx85eLbe07BVkQQEo9samQHP9m/r974TiZeg3bt3aEhu7ZNGi5s0CqVRqz34DlGXEEokOY2o6mxBNQ61nz575NWmilsXhKCKOfXE7tPmwgJOjI/x9+Oix8noOIhEqZmZlNWrYEFazsrLA0SZKElRRqvQsqT/6WIuQhmnDc+L+H7XePxg4AD6Q+MvxY6q5ylVt6c0CA7Zt2qhsZ9zoUUSZj4YMho+yCpvNmjhuLHyUJYl0tWZNhcWE52CojY1tA/eGmdnP7dj29hwHBoNJUczWCV+VloCbCVnWVjbaRHPRl0vdXHnNAgNZLFb6gwcnT50eNvRDSC8rK4fx02i07JyccwmJyvLgskGs/dGHgyFav3L1mjKdy1XMMyanXIKfPvj5/c9l9jRaaPdua9ZvnDZpooDPf/LsmTKLwWDAz/VXX68aN3o0hDbg0kKznToEq1oIZbp27vz12rUTxozx82tCo1Ih0AbDQrp13bpj56IF86EM/BrDz7sy4uZwOHfT7sNCAy8v3SUNQh9rEfIwg4vbEVUs5uJ2yj/+nbenb1FJQX5BnlhcCYk0GoPJYEKiWCzW4WaC+5aSevlcYhKLyYQIel70zI7BChUALQgPDfl86TIanQ5KwXN5fR5pzswZG2I2J01P9vXxaernBzpCpINOffzhkI0xm9l27LkzZ7Zr20a1l+jp07bv2r1q3bry8gqINZStAXOjZ+07cHD9ppjikhKQVC8vz5oyNGfWjJ2798TExooqRc2aBX658DM6nT5r+rSt23eMnzINNBosnDhunLL8oP79YrZuax4YuHrFV7Cqo6Sh6GMtQhomFM2BH36kLet/x46SaYn5YDFnzwlAFisrK+3tuI4OzkSALKsGEnXvVaOGD4NPzXRoBLQGPmrpQS2a79kRq1ydonLv0LhPRsNHYy/geM6eMV1jFsfObvqUyfDRYSSUIS7iVcWOzV4wZ7bG8mqD0lHyfPxJjava0vWxFiEH04bnP313RFvWO+v8Wkx4rgQsxhdAI+8Q1eE5PrndfLCk8PzthrhgXg01TxB5BwGnBuc0zQr4OizM03xbQX1EtIGiaVZY2JwmgrxrEPeem9oK5F8s5t5zBHk3YTAYFcIKOo2O0mkOgFzC16G8nMZQUDQRpN5xF7hnZmVyHbgMOj7N2vRUiiqLS4o93D2Mq46iiSD1jiPXUS6XZ+dki0QiU9uCUOh0uoAvgC9Fn5sPa4KiiSD1DhycPBceHKjaHlWDkAn8gEmlUon2e6x1g6KJIGQgqcbUViB1AIomgiCIAaBoIgiCGACKJoIgiAGgaCIIghgAiiaCIIgBoGgiCIIYgGlEUyIRpz28nVeY87JQ8ZpcFydXVye+f+Pm2l7eiyAIYiaYQDRzX2Zf+euio72zi6Obu2sDCsVKLKksKimMT/qpY5tubi74ThsEQcwXskUzvyDn979TA5u0eFJit+uqLD1PcbmvnytreBteoFs5ZHVo3YXnzH9jOwiCICaBVNGUSiU37v7Rwr/193fo8XclYUGC0WEcqZxy5VHpqsTsPs3sBwe2hgIhnXra2lLJNEwHV65da9kiiMnE5ywgCKKAVNF8lvnYxZn/rNz++N8l/Tr6tPakW1tb21pRWntzKDbU7689CW7IVRTIfOzr3bRm9aqqqtNnz8EnIyursrLS08OjdcugySpv/qkPPl+6fM/2WC8vz3rtBUEQS4FU0SyrKOXz+Jviy1ydHauqrLJfyei28qoqikhaRbGygsQ9v71aGcXPfZmjsfr2uF3Xb9zsG9Xbu4GXPYdDUbw7jGOEGTk5uYuXLtsVu7VWg0EQ5J2EVNEUVlY4cJzuPbvXtZ37s0JpmbjKkal46EtRhbygXObvbpfyx1MH+4CnGY81Vj+bkPDlooWtgoJqaYZEInn2/HktG0EQ5N2EVNGkUmlUKrVKIvRwsJZbWQvFcvgQWQ5Ma3d7CmRRFWi+8Mjfr+m2HTshHgfdVHtU/ep16x88fJSZleXK402dOKFDcHtK9WvOlJH1ixcZYyZNPh9/Min54orVayj/vATts3lzI8JCVZsSi8WHvjt2PiExNy9PzQCpVLpzz97kiyliiTi4XbtpkyZyOOqubp9BH0CDKampMpm8c6eO0dOn0Wg0HUZWVVUd/u67+NNnld0RNuvTF4Ig5EOqaDo7ukhk4haeTFFFaWMX59zSf58A6saxeVVcAFkSqRiKaay+cP7cbTvjFi9Z5sjl9u/bJ6pnD6WOtG/bZlD/fkwm88z5hOVfr/rl+DHijeo1CenWtVFD7/FTpp058TOs1ny+4a59+//48685s2bw3fgZmZmLlyxVZsXt2Xv/fvqSxQuhoy2xO7bH7Zo3O1qtukgkah4YOHHsmJzcvPWbNm3YtPnTeXN0GAmKefrs+VnTp7oLBE+ePl224mv9+0IQhHxIFU0HO25ZWemsPv7R2y8tGBNlx7B+WabQTRe2jasdZc0vv2+c1AUKQDGN1UEiF8yZPWXihJRLqecTk/YfOrxgTnT3rl0hKywkhCjz/oD+R499D14baJDGRsBFtbFW6KlGVZXJZD+fOPntN2ub+jWBVQ/3fxuRy+Un4k+tXbnCzc0NVgcN6AeCqLELfz8/Npvt69Moevr06Hnz582eRfSl0ciffjk5f3Y0+JKQ7unhYWhfiEUA8URufm52TnaFsMLUtiAUFpMl4AvceG7GvVuNVNHkOfMfPrvXqpH7kK6+a/eeHB7Vqa2HE6Q/yipYe/y3D7s2adWI8/BpVmPvAAhOtTXCsbOL6tWzd88eB48cjd25C0QT9kjw3Y7/+FNeXl6FUAhlZFJjnmIPFBQWQtcNG3pryCooBC9y5tx5+rfm5ekhEosLi4p4Li4ajYTc4uJiVWk2ui/EnAHFLCgsCGoe5OzkbGpbEDjMC9LS02CB72rMJeGkiib4cQ09Gz958Xh6X/9uLTw2/PjXtmOKibyWvq6bpoQEeXMeP38IBfR5cQf8RPg39fvfCcV7xm/curUlNnbJokXNmwVSqdSe/QYoy4i1PysbeqnpbDo4OECtZ8+e+TVpopbF4dhB1r64Hdp82Jo8ffacRqM5OzlpM5JGpbKYzLv30pQ+ptF9IeYM+JigmA72DmKx2NS2IBT4Ivz9/G/evmkBognelo2NbQP3hpnZz70d7XdHd2MwmJBeWSl8VVoCiZBlbWWjTTQXfbnUzZXXLDCQxWKlP3hw8tTpYUM/hPSysnIrihXIU3ZOzrmERGV5D3d3iLU/+nAwBMJXrl5TpnO5DvA3OeVS+3ZtbaytoTVlFp1GC+3ebc36jdMmTRTw+U+ePVNmMRiMzp06fvX1qnGjR4PGgbcIzXbqEFzTzgePHjk5Oebl53+7ZcvA/v2IaVONRoIy9usTtTl2O8hoY1+fR4+fGNoXYhFAVA4+Jr5VzUwAhYGvw+ipErJvoyT8O29P36KSgvyCPLG4EhJpNAaTwYRE+B3W4WaCa5mSevlcYhJ4ZxBBz4ue2TFYoSOgJuGhIZ8vXUaj00FrIBYmys+ZOWNDzOak6cm+Pj5N/fyUrznmcDgffzhkY8xmth177syZ7dq2Ue0levq07bt2r1q3rry8IsC/qbI1YG70rH0HDq7fFFNcUgKS6uXlqVHIVq5ZC39debzIiPARHw0lErUZOX7MJ7a2tnv2HygtLW3UqKGhfSGWQlU1prYCeU1tvgsTPLADZLGystLejuvo4EwEyLJqIFH3SEYNHwafmunQyKzp0+Cjlh7UovmeHbHK1Skq9w6N+2Q0fDT2Ao7n7BnTNWZx7OymT5kMHx1GUv65ZkhPI8HZHDNqJHwo1Vc7RQ18n0an6d8XYhEQJxxQNM0K484CUUz1aDjYe3BypyZ37t0DbXVxxnMFbyHoaZoVFuZpvpsQ19KrcT7+pFQqfVVaKpPKHj15vDl2+8B+fbVdYYpYLlYUKxRNswK+C/hSjKuLokkSoI8a09MfPFy/KSYrO9uVx+sVGfnRkMEkG4aQgZXiKJXL5aa2A3mN4gfMSM1E0axrtImjNgID/OO2baknYxAzAT1NcwM9TQSxAFA03w5QNBGk/jE2EjRnrly91jKoBZPJNLUhxoLhOYKYMxYRnl//+8b8RYtHjxg+ctjHRIry8WA1Cy9eusxyn8+NZ88RxKyxlDnNcwmJrVu1PJ+YNPyjocRljAIB/7uD+7VZXkWxgEFpBOc0EcS8sVI8ucrM9UUkEl2+cmX7lpipM6Pvpd0P8Fe8csba2tqRy9UqmpbwS6ARxZUMGJ4jiNliEZ5m6m9XAvz9XZydu3frCs6mf1M/SHyRkaF8+KxYLD5y7PvzSRfy/nlgtnJQUql01959Fy+lQpn27dpOmTCBw7Ez4VjeCHqaCGLumL9oJiQlRYSFgpHhISFfLFs+afxYW1tbwmbi7579B/7463r09Kl8N7fMzKwvln+lHNSuffvvpz/4/LMFDAYzdmfcjt2758ycYeLx6ATnNBHErLGysjLzi9uLi4tv3703ZeKEgoJCZ2cnOoN+7Y8/Owa3l8sV4gKWy2SyX36N/+brlX5NGkMKv/rx2JArr+bXU6dXLl/Kc+FBYv8+UZu2xZrzYCmEp2lZ954jyLuGmc9pXriYIhQKx06aokxJvHChQ/t2ipM91RIDYgoxuHcDr/+OQuFpviwoEIlEcz9dSPlvBkmmG0VtNB1FE0HqHfOf00y4kLzsi8VtW7cmVl9kZMycO7+srEwZntvbc8A1e/r8eRNfX2UtYlB2bMUzs3dsiRHw+apZJA/BIHBOE0HMGyuzFpHnLzLy8vNbqrwc28vT09PD49Ll35oFBhApNBqtW5fOG2O2TBw7BmJz1ZdgMxj0jsHBq75ZP3rEMA+Bu7BSmJeXH6zwUs0XvPccQcwdc/Y0k5KTO3fqaGNtrWohSGTiheTAAH/KP27j1EkT9+zbv27TporyiqZ+fi7OzspBzZw65dDRozFbY0tKStz4bl4eHu3btTXVcPQBTwQhiFlj5uE5cf+PmnkfDBwAH1j45fgxIovJYIBuTv1vXSKLzWZNHDcWPmrpZguG5whi3ljCxe3vFHhxO4KYO+YsmgM//Ehb1v+OHSXTEtKwgLPnsLucPnsOPhlZWZWVlZ4eHq1bBk1WeWmPPkRE9bXcBwQg7zJmHp7/9N0RbVlma3MtsYDwfHvcrus3bvaN6u3dwMuew6EoXhzGIbJycnIXL122K3YrOZYgiAmoDs/N/HrvdwoLCM/PJiR8uWhhK5VrGpRIJBLVyxcQ5O0DnBpzDs/fQeDrMHdP09+v6bYdOyEeB91UvXspKfniitVrKP+8d+yzeXPz8vPv3kv7v6VfEgVu37kLBQ7t3W1tba3WplQq3blnb/LFFLFEHNyu3bRJEzkcDjnDQRBDQdE0KyxgTnPh/LnbdsYtXrLMkcvt37dPVM8ehMCFdOvaqKG38jEqoIwFhYUHDh8pLi7mcrmUahc1MjyspmICcXv23r+fvmTxQiaTuSV2x/a4XfNmR5MzHAQxCOLec1NbgfyLBdx7DhK5YM7sKRMnpFxKPZ+YtP/Q4QVzort37Qp221gr3lirfG+ti7NzuzatEy4kfzBwgEgsTk65tGXj+poNwg/FifhTa1eucKt+cMCgAf02bNpMzlgQxFAYDEaFsIJOo6N0mgMgO/B1wJdiXHVSLzni2NlF9erZu2ePg0eOxu7cBaKpsVhUr177Dh4C0fztylXvBl6eHh41yxQUFIpEoplz59WzyQhSB7gL3DOzMrkOXAbdyAMVqUMqRZXFJcUe7hqERR9McJ0myLx/U7//nfjPW0dkMpnS2Qxu13ZDzOYnT5+ePZ/QIzxctVgV5fUPNYejeEbAvrgd7gIBOWYjiNE4ch0hNsrOyYZfelPbglDodLqAL4AvBWTHiOokieaiL5e6ufKaBQayWKz0Bw9Onjo9bOiHRBaX6wB/IQxv366tjbU1FAD17BUZ8d3xH27evr3o0/nKRiDGv5t2HxYaeHmBa925U8evvl41bvRocEUrhMLcvLxOHYLJGQ6CGAQcnDwXHhyoGmfnEZKBHzCpVCqRSIyrTtbZ86Z+KamXzyUmsZjMhg2950XP7Bj8WuBACj/+cMjGmM1sO/bcmTPbtW0DiRDCjxw7PqRbVzs2W9nIoP79YrZuax4YuHrFV7A6N3rWvgMH12+KKS4pEfD5Xl6eKJqI2SKpxtRWIHUASaI5avgw+GjLHffJaPiopvDd3FycnXtE/Cc2V2uEY2c3fcpk+NS5tQiCINow03vPb92+I6+qUj4SFUEQxEwgQzSJC9c1ovEl9MDPJ3+NCAtVnhpCEAQxE8gQTW3KqI3S0tK79+4Rz/hDEAQxK8wxPOdwOEf27zW1FQiCIBowR9FEEAQxW1A0EQRBDABFE0EQxABQNBEEQQwARRNBEMQAUDQRBEEMAEUTQRDEAMh7G2Vufm52TnZ4SHifb9PJ6RSxFH6d5Xfi1Anj6rKYLAFf4MZzM/pB3AhiECSJJihmQWFBUHPFC4KiNt4np1PEUoC9wrgnGwKwX6Wlp8EC35Vfp0YhiGZIEk3wMUExHewdwOVETxNRA/aKyspK4+rCTuXv53/z9k0UTYQcSBLNCmGFk6OTSCSi0+noaSJqgKdZXl5uXF25XA67FuxgdWsSgmiDJNEk5puqqkFPE1ED9gqjRZMAJzQR0iDv7DmhmDinidQE9orS0lKjq+MrHhEyIcvTpFhBGCWTyQhP05H1ut+iCik5BtTEHGxACGCvKCkpMbo67Fqwg9WhPQiiA/LCc1VP8+AEHyLdhKG6OdiAEMBeUVRUZHR1Yr+qQ3sQRAekXtyuOqdZU6paebFWvO958ErBkasFJBhDGPDrLD8S+kJ0A3tFbUQTQciELNG0UsRQijBK+5xmWID93y8qwvw5R68W4BzVOwXsFS9fvlRLjNu9nefCi4joyWa9fiOpUCg8l3AmLy93/NhJqiVhv8LoHCENssNzbWfP6bZWHX3sph16uulj76Z8RlqOkVftIZYI7BU1RdPN1S03L/fX+BN9evdjsVgiUWX86ZNFRYWurm5qZ34wPEfIhNQTQTrOnnfytbuXLcwvlSanl4LLqRRNCJ8n7X+aUSSGZU9H2vZRDQnNpdlYfdzBuUsTO0eWLRT+5kx2cYVMW+EfpjZOTCsN8mS62lNLKmS7L+VfTDf+XC1S58BekZeXp5YYHtbjFKhkcRFoZXhoxIWLiaCY9vYOYaERaqKJJ4IQMiFvTlP17HnN3FB/+4R7r2AhMe3V8gEeOy7mS2W6YvQJ3V2bujG2JOVlFomlMgpIoY7CDKo1tLY9OT+7WAwdzY7kX3lcJpbiHIC5AHtFTk6OWiKVSo2M6HXmbHxJSfFPP/8AZTgcTs/I3nQaXe2eS0V4jiBkQV54rsPT5LJsmrkztyblgdv4slRaKalq682++rhMW2u2NlY9m9lPP/TseaFYTwN+vVlMeKDH/ywc3tGZx6FmFulbF6lvYK/Iysqqmc5gMCIje509e+pV6Ss2265HRC8mk1nzqkxirpwUSxGE9PBco6fZvak9k2a9e0wjZUqYP0eHaPLsbG2srbJKJEZYQjiYeISZFbBXaBRNgMlg9ojsnZKa/F7HziwWW+N17BieI2RiFmfPw/3tv/xf5p/PXt9I5+VEixnmzaZbl4vkcIhQbdSPh6LqYNyHR0//7/kijYUR8wf2ihcvXmjLpdPpEWE9KNrDcDx7jpCJ6c+eN3Ciudrb3njx7wMXXhSKIZTu2oRz+nZJVpG4X0vu938UutpTgxu9vvSkUiJPfVg2v6dgT2r+g9xKiayquFpGNRZGzB/YK3SIpj7VMTxHSIO8E0HEWaCanmaov/2lB2VS+X/CruT7pWH+9iCaMQm508PdujX1fpwvAn0EuSQKbDqfO6aLy5QQV7qt9d0s4dfxWSJplbbCiJkDe8WzZ8+Mrm70szgRxAjIm9OUVVPT09x3Wf0CPQC8RfjAwq1M4aT9T5XpOy/mEwtlIhlIpFotbYXVesT7Js0N2CuePHlidHXYr3BOEyENk509J56XYQ4P7EBMDuwVjx49Mro6nj1HyITs8FzpaRLPyzCHB3YgJgf2itqIJobnCJmQJJpMJrNCWEGn0QlP0xwCZHOwASGAveLBgwdG14VdC3awujUJQbRBkmi6C9wzszK5Dlx8cjtSk9p4mpWiyuKSYg93j7o1CUG0QZJoOnId5XJ5dk42PrkdqQnsFQlJCcbVpdPpAr4AdjAM0hFyIEk0YYfmufBg5zb6pYPI28xk4/cK+DGWSqUSiTG3hyGIEZB3IkhSDWndIQiC1Ad42Q2CIIgBoGgiCIIYAIomgiCIAaBoIgiCGACKJoIgiAGgaCIIghgAiiaCIIgBoGgiCIIYAIomgiCIAaBoIgiCGACKJoIgiAGgaCIIghgAiiaCIIgBoGgiCIIYAIomgiCIAaBoIgiCGACKJoIgiAGgaCIIghgAiiaCIIgBkC2apRWlN+5cy3mZXSWXq2VZWVvzXQQtmwVzWBySrUIQBNETskUz7cFNe7ZDl+BQOo2uliUSi27du56WfrN9q84kW4UgCKInZItmQdHL3qH9aDUUEwAZDQpofSrpBGnGPH361MPDg0qlktajOfDq1atz585FRkba29vXYbPv5sZE3kHIFk0bGxuNikkAWVBAW25MTAyLxRo1apTqkSmXy48ePVpQUDBjxgxDjTlx4sSIESMcHR2LiooOHjxItJCRkZGcnFxaWsrj8T744APVLOMAs4lejG6hDsnPzz958mRQUFDdKiZFZWPWbbMIYm6QLZq0N3kiugtUVlb+9ddfHTp0UKbcvXsXdK2WVjk4OIwbN45YTkxMbNiwIXRBp9PVst4Cfv/99/Dw8AYNGpjaEASxVMgWTSqVVpsCrVq1un79evPmzdlsNqyKxeIrV65AIihpbayytrYGH5ZYLikpgfYJxVTLeguIiooytQkIYtlYmGgGBARkZWVdvXo1LCyMUu03gScIiaqiCUp66dKlp0+fVlVVgc/YtWtXGu11mzKZDKqkpaVB9K3aLBGDT506NS4uDlaPHTtmZWXVpk2b9u3bq4bnUP3y5csPHz6USqXe3t7dunVjMBiQvm3btpYtW4LPKxQK3xjIa2tEldjY2KZNm2ZmZr569Qok+7333vPz86P8N9JXGgYLv/zyi4uLS0ZGBpVKBcWH3Pv378MYuVwubCg+n0+pnseA7Zaeni4SicDT7N69O5PJ1Gi8jg2oNhCNG1PPMUK//v7+UAYM8/X1DQ0NVc7MnDt3Lj8/v7i4mMPhQO9gAySCMX/88cedO3eU3RGbQp++EKQOIV00bd8kmjoLgJbB0f7999+DdwnH2M2bNz/44ANIVC2TnJxcXl7+8ccfw/KZM2cuXLjQo0cPIguOrufPn0N8am9vD1pz4sR/TjpBg5MmTQJhGjp0qMa5ud9++y03N7d3796gTRcvXgRliYiIgHQ4XMEzBUv02ABaG1FFIpGAMXD8w08CyF9CQoKPj4+trdYvC7QVhK9Tp04PHjwAZYRfEdAaqAtuONQdPnw4lIFlUOHIyEjQFKJfWNZovI4NqIqOjanPGKFfgUDQuXNnMD6xGsIeALQPhgN17927d+rUKfhSwN8HxYRV0FYYV0FBQXx8vP59IUgdYmFzmoCrq2tgYGBqaiqICLgqsKo6pwl+B6gMHPCEG9WlS5ejR4/CgQ0aBB7NrVu3QB3c3Nwo1ZOVBlkOng5UHzRoEHEKBY7qpKQkZS6Imj7nQHQ3okqLFi2IBsHhBR0sKysDt1FHy/ArAn+DgoKuXbvWtm1boi4sfPfdd0S/8AMzYMAAYtSw3UBcNBqvYwOqdqdjY+o/RqgLPiz4yCCFx48fh15AHCGdcKuJQf3555/gWkL7N27cADUEPYV05abQvy8EqSvIFk06nSGTSW1sNPcLWVDgjY2AS3XgwAFYGDlypFoWuEhwICkPKliA1YqKCgj0IAsUwdnZ2TjLoTo4R+DkGlfd6EYIBxNGoU9hQumUKC8zgH7BewVh0sdCbRtQrZi2jWnEGKEXqAK92NnZwSp4lNevXwetFIvFlGqBhlyhUFjzZ6NOvhQEMQiyRdOJy3tZ9NLFkVfz0iI4CCELCryxEQgwR4wYQSyoZREniIqLi4njuaSkBIJ3IpEQlMLCQnBOjbCcODU0atQoQ11Uiork1aYRAthKRtQiNpQ+/erYgKro2JhGjBHagf2B6IW45CsqKgqCd0jcsmULpfqXA3zS7OxsNd2s/fZEEEMhWzR5Tq6FJQUvsp/VdJ0UByeL4+TgLJW+WRfUXColcJhBcJeSkkJMw8FCQEAAEfTBgQdZ58+fJ+b7CgoKDLIcvDZfX99Tp0699957cOiCEwSuUKNGjd5YEQQrNzcXFpycnIxuhACqQJQNQTfUevLkif7Gw9iJfsFJh0gcvE5ogTjBooaODajWoLaNqf8Y8/PzQSghF2JqiKyJuWmRSAQLYMarV6/S0tKUhZs3b37x4kVI5/F4L1++NLQvBKkryBZNmUzOc3Lj89zVzt5Qqt0xcKOIiKw2hISEwKF++PBh6MLHx6dLly7KrNDQ0NTU1HPnzkEvfD6fCAb1Jzw8/MqVK4mJiRBIglKA+uhzfIIcXLhwAfymgQMHGt0IQVhYGOhLeno6CAe4eAbdfhMREXH16lWwBEJae3t7UHCNoknRuQFV0bEx9RzjmTNn4C8E/v7+/u3btycSoSTI8cmTJ0EfQRCVzYIsQgo0W1lZ6eLiYmhfCFJXkC2aoIzgShhXV9vVPHCcqGZByKbt/CmEeKHV6GhBrRfVLGi5ezV6GkYQXI2qeRob0dGgctXDw4OYlyAAL49SY/iqy6pZMPau1bzReB0bUBVtG5Oi3xgp/1wzpJYIXq3GZkHBO1ZDqZ6j2Lp1KzHbq2dfCFJX4KPhEMsjOzsbtLXmTCuCkACKptkRExOjMb0297+/BcjlcgjM4e/Lly+Tk5ODgoJqzrQiCAmgaJod77g4aiMvLy8xMZG4TSgwMLBNmzamtgh5R0HRREyDob8NfD5/2LBh9WQMgugPiiaCIIgBoGgiCIIYAIomgiCIAaBoIgiCGACKJoIgiAGgaCIIghgAiiaCIIgBoGgiCIIYAIomgiCIAaBoIgiCGACKJoIgiAGgaCIIghgAiiaCIIgBoGgiCIIYAIomgiCIAaBoIgiCGAAZokmnG/DSRDNHJJKY2gQEQUwJSZ6mXC7Pzs1+/iJDWCkkp8c6hMlgNvDyFLgJrK2tU6+m6lOFxWQJ+AI3nlvNNxUjCGLRkCSaoJgvXmQ42tm7O/HI6bEOEYpFYDwseAg8OrbrwGIx31iluKT40ZPHsMB35de7fQiCkAhJogk+Js/RmcdztaVaXqgulUhs86kwBBBNPatwHbi+jXzS0tNRNBHkLYMk0YSo3M2Nz2SxbG0t77WrUikdAvPn2RkG1QLdrBBW1JNJCIKYCpJE08rKisVmV7+ouoqcHusQGxsbMN6I2Umc0ESQtw/yLjmqVkxLRbfxIrE4/cHDJr6+DAadNJMQBDEJZHmaCq+LcLssz9MkLIchaMwFxbx9+46wsvLWndtBzZvT6f/qprYqCIJYLmR5mm+BemgaglgsvnPnLigmCKtIJL515w7oJo1G01EFQRCLhmxPs8ryHE1dnuadu/cqhEIWk+nv3/R+enp5ecWt23fatmn9uiKqJoK8deBtlLWivKKCyWA0axZIp9GaBwbevnMXUkxtFIIg9Qh54bmle5oavcYu73VSLlOp1NatWv63Zr3ahSCICSAvPCeno/rDiCG8BaNGEEQNsj1NS0SHp/mmmnVtCoIgpgY9TX1BTxNBEAqZJ4Is3tP8h4oKfR/UZLlDRhBEG+TdRmm5CvL6kqN/7NfnKUcIgrytYHiuLxieIwhCwRNB+oAnghAEUYKepr6gp4kgCAU9TX3Q4Wleuvwbk8Fo3rwZnUaTSCTEHUH/XvFuqSNGEEQreBtlrWCzWKCSd+7cfX3vefVdlaY2CkGQeoT8R8NZHjoe2NEsMAC8ywqh8PrfN6qqqhgMeovmzf6tiK4mgrx14KPh9EbTEGg0WrNmgcTzNOl0Wotmzf59LpyWKgiCWDToab4Z3Q8hVjzfqHkz4sntqk8g1lEFQRDLBec06wDQzRbNAk1tBYIgZECSaLLZ7JJXJVwHLotlR06PdUtxSTEMwaAqpaWlhlZBEMT8IUk03QWCx48f+/r4crlccnqsQ4qLi8F4GIL+VUAxn2dk8N3wpecI8rZBkmi6OLtUVVWl3U+zxFeBs5gsgYBfPQT5rTu39anCYDBAMR25jjKZrL7NQxCETEgSTZAbN1dXd4G7JZ4OArmXyaSE/IWFhOlZRSqVgr9Zz6YhCEI2ZIimSCSp/i8hoa/6RiQqNLUJCIKYEjx7jiAIYgAomgiCIAaAookgCGIAKJoIgiAGgKKJIAhiACiaCIIgBoCiiSAIYgAomgiCIAaAookgCGIAKJoIgiAGgKKJIAhiACiaCIIgBoCiiSAIYgAomgiCIAaAookgCGIAKJoIgiAGgKKJIAhiACiaCIIgBoCiiSAIYgC2Z86cMbUNCIIgFsP/A6qKOXPiVL3KAAAAAElFTkSuQmCC" name="images5" align="left" width="444" height="317" border="0"&gt;&lt;br clear="left"&gt;&lt;span style="font-style: normal"&gt;Si
vous voulez que vos titres commencent impérativement sur une
nouvelle page, allez dans le panneau de style, puis dans l’onglet
&lt;/span&gt;&lt;i&gt;Enchaînement&lt;/i&gt;&lt;span style="font-style: normal"&gt; de votre
titre. Cochez la case &lt;/span&gt;&lt;i&gt;Insérer &lt;/i&gt;&lt;span style="font-style: normal"&gt;et
laisse&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
les autres champs aux valeurs par défaut.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images3" align="left" width="643" height="556" border="0"&gt;&lt;br clear="left"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__13831_757466230"&gt;&lt;/a&gt;5 Faire
une page de garde&lt;/h1&gt;
&lt;p&gt;Pour faire une vraie page de garde, avec du texte centré sur la
page, des entêtes et pieds de page spécifiques, c’est assez
simple. Placez-vous sur la page à convertir. Allez dans &lt;i&gt;Format &amp;gt;
Page de titre…&lt;/i&gt;&lt;span style="font-style: normal"&gt; Sélectionne&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;i&gt;Convertir les pages existantes en page de titre&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images8" align="left" width="595" height="604" border="0"&gt;&lt;br clear="left"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p style="font-style: normal"&gt;Vous pouvez choisir si la page doit
être numérotée et à quel chiffre la numérotation doit reprendre
après cette page.&lt;/p&gt;
&lt;p&gt;Pour mettre un texte (le titre de votre document par exemple) bien
au centre de la page, allez dans &lt;i&gt;Insérer &amp;gt; Cadre…
&lt;/i&gt;&lt;span style="font-style: normal"&gt;Sélectionne&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
la largeur comme relative et à 100&amp;nbsp;%. Dans la section position,
choisissez &lt;/span&gt;&lt;i&gt;Centré&lt;/i&gt;&lt;span style="font-style: normal"&gt;
pour les &lt;/span&gt;&lt;span style="font-style: normal"&gt;alignement&lt;/span&gt;&lt;span style="font-style: normal"&gt;s&lt;/span&gt;&lt;span style="font-style: normal"&gt;
vertica&lt;/span&gt;&lt;span style="font-style: normal"&gt;ux&lt;/span&gt;&lt;span style="font-style: normal"&gt;
et horizonta&lt;/span&gt;&lt;span style="font-style: normal"&gt;ux&lt;/span&gt;&lt;span style="font-style: normal"&gt;.
&lt;/span&gt;&lt;span style="font-style: normal"&gt;Dans l’onglet &lt;/span&gt;&lt;i&gt;Bordures&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
&lt;/span&gt;&lt;span style="font-style: normal"&gt;vous pouvez&lt;/span&gt;&lt;span style="font-style: normal"&gt;
supprime&lt;/span&gt;&lt;span style="font-style: normal"&gt;r&lt;/span&gt;&lt;span style="font-style: normal"&gt;
la bordure.&lt;/span&gt;&lt;span style="font-variant: normal"&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;/span&gt;Ceci est aussi valable pour les autres pages.&lt;img src="data:image/png;base64,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" name="images9" align="middle" width="643" height="534" border="0"&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3212_976366088"&gt;&lt;/a&gt;6 Le
sommaire automatique&lt;/h1&gt;
&lt;p&gt;Maintenant que vous savez faire des titres, vous aimeriez bien les
intégrer dans votre sommaire. Eh bien LibreOffice va le faire pour
vous. Dans la barre d’outils, allez dans &lt;i&gt;Insertion&lt;/i&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;span style="font-style: normal"&gt;&amp;gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;i&gt;Index et tables&lt;/i&gt;&lt;span style="font-style: normal"&gt; &lt;/span&gt;&lt;span style="font-style: normal"&gt;&amp;gt;
&lt;/span&gt;&lt;i&gt;Index et tables&lt;/i&gt;&lt;span style="font-style: normal"&gt;…&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images10" align="bottom" width="643" height="339" border="0"&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Valide&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
avec OK. Vous avez un sommaire automatique&amp;nbsp;! Libre à vous de
parcourir toutes &lt;/span&gt;&lt;span style="font-style: normal"&gt;les options
&lt;/span&gt;&lt;span style="font-style: normal"&gt;proposées. &lt;/span&gt;&lt;span style="font-style: normal"&gt;Par
défaut, cette table s’appelle &lt;/span&gt;&lt;i&gt;Table des matières&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
Vous pouvez la renommer en modifiant son champ &lt;/span&gt;&lt;i&gt;Titre&lt;/i&gt;&lt;span style="font-style: normal"&gt;
comme ci-dessus.&lt;/span&gt;&lt;span style="font-style: normal"&gt; Je vous
conseille fortement de laisser cochée la &lt;/span&gt;&lt;span style="font-style: normal"&gt;case&lt;/span&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;i&gt;Pr&lt;/i&gt;&lt;i&gt;otégé contre toutes modifications &lt;/i&gt;&lt;i&gt;manuelles.&lt;/i&gt;&lt;span style="font-style: normal"&gt;
Pensez également à faire un clic droit puis &lt;/span&gt;&lt;i&gt;A&lt;/i&gt;&lt;i&gt;ctualiser
&lt;/i&gt;&lt;i&gt;l’index/&lt;/i&gt;&lt;i&gt;la table&lt;/i&gt;&lt;span style="font-style: normal"&gt;
de façon à ce que LibreOffice prenne en compte les modifications
que vous avez apportées aux titres (ajouts, suppressions,
déplacements à une page différente…). &lt;/span&gt;&lt;span style="font-style: normal"&gt;Vous
pouvez également aller dans &lt;/span&gt;&lt;i&gt;Outils &amp;gt; Actualiser &amp;gt;
Tout actualiser&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Pour modifier l’apparence du
contenu de la table des matières, faites un clic droit sur une
entrée puis sélectionne&lt;/span&gt;&lt;span style="font-style: normal"&gt;z&lt;/span&gt;&lt;span style="font-style: normal"&gt;
&lt;/span&gt;&lt;i&gt;éditer le style de paragraphe&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
Vous pouvez également passe&lt;/span&gt;&lt;span style="font-style: normal"&gt;r&lt;/span&gt;&lt;span style="font-style: normal"&gt;
par l’écran de style en sélectionnant une des entrées &lt;/span&gt;&lt;i&gt;Table
des matières&lt;/i&gt;&lt;span style="font-style: normal"&gt;. Vous avez 10
niveaux de numérotation à votre disposition.&lt;/span&gt;&lt;/p&gt;
&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;b&gt;&lt;span style="font-style: normal"&gt;Sommaire
ou table des matières&amp;nbsp;? Le sommaire est plus synthétique &lt;/span&gt;&lt;span style="font-style: normal"&gt;(3-4
niveau de titre maximum) &lt;/span&gt;&lt;span style="font-style: normal"&gt;que
la table des matières et est placé en début de document.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__969_142577672"&gt;&lt;/a&gt;7 La
correction orthographique et grammaticale&lt;/h1&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__13984_757466230"&gt;&lt;/a&gt;7.1 La
correction orthographique&lt;/h2&gt;
&lt;p&gt;Dans l’écran de style, vous pouvez également sélectionner une
langue pour chaque entrée. Comme vous pouvez ajouter des entrées,
vous pouvez créer un corps de texte en français et un autre en
anglais, ce qui vous simplifiera la vie.&lt;/p&gt;
&lt;p&gt;&lt;img src="data:image/png;base64,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" name="images6" align="bottom" width="643" height="384" border="0"&gt;&lt;/p&gt;
&lt;p&gt;Pour des modifications de langues plus ponctuelles, faites un clic
gauche sur la langue dans la barre du bas et sélectionnez plus. Dans
l’onglet police, sélectionnez la langue que vous désirez. Vous
pouvez également choisir aucune pour n’avoir aucune correction
(car vous êtes vraiment bon en orthographe, ce paragraphe contient
du code…)&lt;/p&gt;
&lt;p&gt;Si vous voyez la langue avec un trait bleu à côté, cela veut
dire quelle est installée, sinon c’est à vous de l’ajouter.
Sous Linux, consultez votre gestionnaire de paquets, sous Windows,
allez voir
&lt;a href="http://extensions.libreoffice.org/extension-center/dictionnaires-francais"&gt;http://extensions.libreoffice.org/extension-center/dictionnaires-francais&lt;/a&gt;.&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__13986_757466230"&gt;&lt;/a&gt;7.2 La
correction grammaticale&lt;/h2&gt;
&lt;p&gt;LibreOffice ne propose pas de correcteur grammatical par défaut.
Heureusement, la communauté propose des extensions pour pallier ce
problème. Vous pouvez installer &lt;i&gt;LanguageTools&lt;/i&gt; qui supporte de
nombreuses langues et &lt;i&gt;grammalecte&lt;/i&gt; qui ne supporte que le
français mais renvoie moins de faux positifs.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.languagetool.org/"&gt;http://www.languagetool.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dicollecte.org/grammalecte/"&gt;http://www.dicollecte.org/grammalecte/&lt;/a&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3214_976366088"&gt;&lt;/a&gt;8 Divers&lt;/h1&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__3216_976366088"&gt;&lt;/a&gt;8.1 Puces
et numérotation&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Pour construire une liste, allez
dans le menu &lt;/span&gt;&lt;i&gt;Format &amp;gt; Puces et numérota	t&lt;/i&gt;&lt;i&gt;ion&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
De nombreux formats de puces et de numérotation sont disponibles. Et
même des plans&amp;nbsp;! Faites votre choix.&lt;/span&gt;&lt;/p&gt;
&lt;h2 class="western" style="font-style: normal"&gt;&lt;a name="__RefHeading__3218_976366088"&gt;&lt;/a&gt;
8.2 Les divers collages&lt;/h2&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Lorsque vous collez un texte, par
défaut, LibreOffice conserve le formatage. Néanmoins, parfois vous
désirez vous en débarrasser. Pour cela, utilisez le &lt;/span&gt;&lt;span style="font-style: normal"&gt;raccourcis&lt;/span&gt;&lt;span style="font-style: normal"&gt;
clavier &lt;/span&gt;&lt;i&gt;Ctrl + Maj + V&lt;/i&gt;&lt;span style="font-style: normal"&gt;
et sélectionnez texte non formaté. Les autres options de texte
garde une partie du formatage.&lt;/span&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__993_142577672"&gt;&lt;/a&gt;9 Citations&lt;/h1&gt;
&lt;p lang="en-US"&gt;&lt;i&gt;«&amp;nbsp;Note that underlining for emphasis is
considered bad practice in the publishing world. Underlining is only
used when the output device can’t do highlighting in another way —
for example, when using a typewriter.&amp;nbsp;»&lt;/i&gt;&lt;/p&gt;
&lt;p lang="en-US"&gt;Michel Goossens et al. in the LATEX Companion&lt;/p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p lang="en-US"&gt;&lt;i&gt;«&amp;nbsp;Perhaps poets who wish to speak in &lt;font size="1" style="font-size: 8pt"&gt;a
still small voice&lt;/font&gt; will cause future books to make use of
frequent font variations, but nowadays it’s only an occasional font
freak &lt;font size="1" style="font-size: 8pt"&gt;(like the author of this
manual)&lt;/font&gt; who likes such experiments.&amp;nbsp;» &lt;/i&gt;
&lt;/p&gt;
&lt;p lang="en-US"&gt;Donald Knuth in the TEXbook&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__13988_757466230"&gt;&lt;/a&gt;10 Auteur
et licences&lt;/h1&gt;
&lt;p&gt;Ce document a été écrit par Julien E&lt;span style="font-variant: small-caps"&gt;nselme&lt;/span&gt;,
élève à l’école Centrale Marseille pour l’usage de tous ceux
qui veulent. Vous pouvez envoyer vos suggestions à
&lt;a href="mailto:jenselme@centrale-marseille.fr"&gt;jenselme@centrale-marseille.fr&lt;/a&gt;
et trouver une version actualisée de ce document (et peut-être des
tutos sur les autres logiciels de la suite bureautique LibreOffice)&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;en odt&amp;nbsp;:
	&lt;a href="http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_basique.odt"&gt;http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_basique.odt&lt;/a&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;en pdf&amp;nbsp;:
	&lt;a href="http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_basique.pdf"&gt;http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_basique.pdf&lt;/a&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p align="left"&gt;en ligne&amp;nbsp;:
	&lt;a href="http://www.jujens.eu/posts/2013/Dec/02/tuto_LibreOffice_Writer_basique/"&gt;http://www.jujens.eu/posts/2013/Dec/02/tuto_LibreOffice_Writer_basique/&lt;/a&gt;&lt;/p&gt;
&lt;/ul&gt;
&lt;p&gt;Ce document est distribué sous Creative Commons BY-SA v3 (Parité,
partage à l’identique). Pour plus d’information, voir&amp;nbsp;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://creativecommons.org/licenses/by-sa/3.0/legalcode"&gt;https://creativecommons.org/licenses/by-sa/3.0/legalcode&lt;/a&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;11 Remerciements&lt;/h1&gt;
&lt;p&gt;Je remercie chaleureusement tous ceux qui m’ont conseillé et
m’ont signalé les coquilles, imprécisions anciennement contenues
dans ce document. Mes remerciements vont en particulier aux membres
de la liste Ginfo de l’école pour leur nombreux conseils et
corrections, ainsi qu’au secrétaire de l’association la mouette.&lt;/p&gt;
&lt;div id="sdfootnote1"&gt;
	&lt;p class="sdfootnote"&gt;&lt;a class="sdfootnotesym" name="sdfootnote1sym" href="#sdfootnote1anc"&gt;1&lt;/a&gt;What
	You See is What You Get, ce que vous voyez est ce que vous obtenez.
	À opposer à WYSIWYM — What You See Is What You Mean, ce que vous
	voyez est ce que vous pensez.&lt;/p&gt;
&lt;/div&gt;
&lt;div id="sdfootnote2"&gt;
	&lt;p class="sdfootnote"&gt;&lt;a class="sdfootnotesym" name="sdfootnote2sym" href="#sdfootnote2anc"&gt;2&lt;/a&gt;LibreOffice
	propose également de tels outils. Se reporter à la partie avancée.&lt;/p&gt;
&lt;/div&gt;
&lt;div title="footer"&gt;
	&lt;p align="right" style="margin-top: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;br&gt;
	&lt;/p&gt;
&lt;/div&gt;
</content><category term="Libreoffice"></category><category term="LibreOffice Writer Tutoriel débutant"></category></entry><entry><title>De drupal 6 à drupal 7 : drush sup</title><link href="//www.jujens.eu/posts/2013/Oct/30/drupal6-vers-drupal7/" rel="alternate"></link><published>2013-10-30T00:00:00+01:00</published><updated>2013-10-30T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-30:/posts/2013/Oct/30/drupal6-vers-drupal7/</id><summary type="html">&lt;p&gt;Pour le projet &lt;a class="reference external" href="http://assos.centrale-marseille.fr"&gt;multi-assos&lt;/a&gt; j'ai
dû migrer trois sites webs en drupal 6 vers drupal 7. Voilà mon petit
retour d'expérience (un autre suivra bientôt sur le module
&lt;a class="reference external" href="http://drupal.org/project/migrate_d2d"&gt;migrate_d2d&lt;/a&gt; qui m’a permi
de migrer deux des trois sites). Ici c'est la méthode utilisée pour le
&lt;a class="reference external" href="http://forum.centrale-marseille.fr"&gt;forum&lt;/a&gt;. Ce site a …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Pour le projet &lt;a class="reference external" href="http://assos.centrale-marseille.fr"&gt;multi-assos&lt;/a&gt; j'ai
dû migrer trois sites webs en drupal 6 vers drupal 7. Voilà mon petit
retour d'expérience (un autre suivra bientôt sur le module
&lt;a class="reference external" href="http://drupal.org/project/migrate_d2d"&gt;migrate_d2d&lt;/a&gt; qui m’a permi
de migrer deux des trois sites). Ici c'est la méthode utilisée pour le
&lt;a class="reference external" href="http://forum.centrale-marseille.fr"&gt;forum&lt;/a&gt;. Ce site a beaucoup de
nodes (plus de 16 000) mais reste simple dans sa construction.&lt;/p&gt;
&lt;div class="section" id="pourquoi-drush-sup"&gt;
&lt;h2&gt;Pourquoi drush sup&lt;/h2&gt;
&lt;p&gt;Il existe plusieurs outils pour transférer du contenu d'un drupal vers
un autre (node export p. ex.) mais pour migrer de drupal 6 et 7 ce qui
me semble le mieux c’est drush sup. Il migre le contenu, télécharge les
modules (dont les thèmes) et les active, copie les fichiers,… sur le
site drupal 7 ce qui est plutôt sympa. Bref, en théorie une fois que
vous avez finis la migration, votre site d7 est une copie conforme du d6
(enfin en théorie).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="preparation"&gt;
&lt;h2&gt;Préparation&lt;/h2&gt;
&lt;p&gt;Étape 1 : télécharger le module drush sup avec drush sup&lt;/p&gt;
&lt;p&gt;Étape 2 : faire une copie de test des sites (il serait dommage de casser
le vrai site).&lt;/p&gt;
&lt;p&gt;Étape 3 : mettre en place les alias drush (pour le drupal 6 et le drupal
7) en éditant le fichier ~/.drush/aliases.drushrc.php comme suit (à
adapter à votre configuration) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$aliases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;toto&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;uri&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;toto.local&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;root&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/var/www/local&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Étape 4 : vérifier la disponibilité des modules et thèmes en drupal 7.
Drush sup est très fort mais il ne fait pas de miracle non plus ;-)&lt;/p&gt;
&lt;p&gt;Vous êtes prêt. Il vous suffit de lancer : drush &amp;#64;d6 sup &amp;#64;d7 et de
suivre les instructions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="la-migration"&gt;
&lt;h2&gt;La migration&lt;/h2&gt;
&lt;p&gt;Normalement, le script de migration détaille bien les étapes et les
questions posées sont claires. Il n’y a pas de raison majeure que ça se
passe mal.&lt;/p&gt;
&lt;p&gt;Il est bon de savoir que drush fait des sauvegardes et peut donc
rétablir le site d7 a un point antérieur de la migration (tout refaire,
juste après la migration des modules,…).&lt;/p&gt;
&lt;p&gt;Le point qui m’a posé problème est en général la migration du contenu
qui bloque. Parfois en retentant ça passe. Pas compris pourquoi.&lt;/p&gt;
&lt;p&gt;Un point bizarre que j’ai eu sur un site : drush sup refusait de migrer
mes modules via l’option qui permet de tout migrer en un coup. Mais en
les prenant un à un, c’est passé.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Pour les sites relativement simples tels que ceux que l’on a sur assos
la migration ne doit pas faire peur. Drupal 7 est suffisament mature,
avec suffisament de modules pour que tout se passe bien. La migration
demande quand même pas mal de tests au préalable pour régler les petits
problèmes tels que les blocs qui disparaissent ou le thème qui casse. Le
nombre de node ne doit pas faire peur. Par contre, il faut se méfier des
sites avec des modules étranges.&lt;/p&gt;
&lt;p&gt;Concernant les deux sites pour lesquels je n’ai pas pu faire du drush
sup : le premier avait une base de données pourrie (un de mes
prédécesseurs avait tenté une migration directement sur le serveur ce
qui a pourri la base de données, même en supprimant les tables de drupal
7, il restait des problèmes). Pour le second, les très nombreuses images
indispensables au site ne sont pas migrées et il se trouve que c’est un
peu plus simple de rattraper ça à partir du résultat de migrate_d2d.&lt;/p&gt;
&lt;p&gt;Voilà. Si vous avez des questions ou des remarques, les commentaires
sont là.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="Drupal"></category><category term="drush"></category></entry><entry><title>De drupal 6 à drupal 7 : migrate_d2d</title><link href="//www.jujens.eu/posts/2013/Oct/30/drupal6-vers-drupal7-migrate/" rel="alternate"></link><published>2013-10-30T00:00:00+01:00</published><updated>2013-10-30T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-30:/posts/2013/Oct/30/drupal6-vers-drupal7-migrate/</id><summary type="html">&lt;p&gt;Après &lt;a class="reference external" href="/posts/2013/Oct/30/drupal6-vers-drupal7/"&gt;la première partie sur drush
sup&lt;/a&gt;, voilà la
deuxième et dernière partie de mon retour d'expérience sur les
migrations Drupal. Aujourd’hui c'est le module
&lt;a class="reference external" href="http://drupal.org/project/migrate_d2d"&gt;migrate_d2d&lt;/a&gt; (pour migrate
drupal to drupal) qui est à l’honneur. Je ne parlerai ici que de la
version 2.1 (encore en développement …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Après &lt;a class="reference external" href="/posts/2013/Oct/30/drupal6-vers-drupal7/"&gt;la première partie sur drush
sup&lt;/a&gt;, voilà la
deuxième et dernière partie de mon retour d'expérience sur les
migrations Drupal. Aujourd’hui c'est le module
&lt;a class="reference external" href="http://drupal.org/project/migrate_d2d"&gt;migrate_d2d&lt;/a&gt; (pour migrate
drupal to drupal) qui est à l’honneur. Je ne parlerai ici que de la
version 2.1 (encore en développement à l'heure où j'écris ces lignes)
car c'est avec elle que le projet introduit &lt;em&gt;migrate_d2d_ui&lt;/em&gt; une joli
interface pour vous simplifier la tâche.&lt;/p&gt;
&lt;p&gt;Ce module très sympa vous permet de repartir sur de bonnes bases, dans
un site Drupal 7 tout neuf. Il m'a été très utile pour migrer le site
des &lt;a class="reference external" href="http://assos.centrale-marseille.fr/annales"&gt;annales&lt;/a&gt; (accessible
uniquement pour les élèves de l'école) (dont la base de données était
corrompue ce qui empêchait drush sup de fonctionner) et pour le &lt;a class="reference external" href="http://assos.centrale-marseille.fr/expat"&gt;blog
des expats&lt;/a&gt; dont la version
drupal 7 est en cours de validation de notre côté pour lequel drush sup
ne migre pas correctement les images.&lt;/p&gt;
&lt;div class="section" id="preparation-et-migration"&gt;
&lt;h2&gt;Préparation et migration&lt;/h2&gt;
&lt;p&gt;Ce coup ci, votre site drupal 7 ne va pas se créer tout seul. Il faut
donc tout d'abord créer un site drupal 7 neuf, comme d'habitude. Activer
tout les modules nécessaires, créer vos types de contenu avec les bons
champs, les rôles et les vocabulaires de taxonomie.&lt;/p&gt;
&lt;p&gt;Une fois que le site drupal 7 est prêt, il faut télécharger et activer
les modules &lt;em&gt;migrate&lt;/em&gt; et &lt;em&gt;migrate_d2d&lt;/em&gt; (pour le moment, prendre
les&lt;strong&gt;versions de développement&lt;/strong&gt; des deux modules, sinon vous n’aurez
pas droit à l'interface).&lt;/p&gt;
&lt;p&gt;Direction &lt;em&gt;Contenu &amp;gt; Migrate &amp;gt; Import from drupal&lt;/em&gt;. Après l'interface
détaille bien les étapes. On commence par remplir les infos sur la base
de données, puis on choisit pour chaque type de contenu du drupal 6 le
type de contenu d'arrivée dans le drupal 7. Idem pour les rôles. Pour
les fichiers, il suffit de lui donner l'emplacement sur le serveur. On
sauvegarde.&lt;/p&gt;
&lt;p&gt;Ensuite, retour sur le dashboard, on sélectionne ce qu’on veut importer
et c'est parti !&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="les-problemes"&gt;
&lt;h2&gt;Les problèmes&lt;/h2&gt;
&lt;p&gt;J'ai eu quelques problèmes avec les préfix de bases de données qui
n'étaient apparament pas pris en compte. J’ai retesté hier et c'est
passé. Le problème a dû être corrigé en amont.&lt;/p&gt;
&lt;p&gt;Les formats de texte n’étaient également pas toujours bien pris en
compte. Mais ça, c'est facile à régler avec du SQL.&lt;/p&gt;
&lt;p&gt;Le gros problème est que si la table &lt;em&gt;file_managed&lt;/em&gt; était bien remplie,
les tables file_usage et celles qui spécifient dans quel champ le
fichier est utilisé sont restées désespérément vides. De même pour la
taxonomie. Les termes du vocabulaire sont bien créé mais ils ne sont pas
associé à chaque contenu. Du coup j’ai dû faire un script pour récupérer
les données dans le Drupal 6 pour remplir les tables du Drupal 7.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Cela conclue mes migrations de Drupal 6 à 7. En résumé, quand drush sup
fonctionne, c’est génial. On a alors vraiment l'impression que tout est
magique et automatique. Par contre, sans ça devient galère, surtout s'il
faut aller dans la base de données pour finir la migration. Ça allonge
considérablement le temps nécessaire pour terminer. D'autant plus que je
n'avais aucune expérience sur les bases de données de Drupal avant. Mais
bon, c'est l'occasion d'apprendre ;-)&lt;/p&gt;
&lt;p&gt;Les migrations vers drupal 7 c'est bientôt fini pour nous. Les derniers
Drupal 6 qui restent sont en train d'être refait depuis zéro par leur
webmaster respectif. En tout cas, je comprends pourquoi sur
&lt;a class="reference external" href="http://drupal.org"&gt;drupal.org&lt;/a&gt; il aura fallu plus d’un an pour faire
la migration.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="Drupal"></category></entry><entry><title>Tutoriel d’utilisation avancé de LibreOffice Writer</title><link href="//www.jujens.eu/posts/2013/Oct/25/tuto_LibreOffice_Writer_avance/" rel="alternate"></link><published>2013-10-25T00:00:00+02:00</published><updated>2013-10-25T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-25:/posts/2013/Oct/25/tuto_LibreOffice_Writer_avance/</id><summary type="html">
&lt;p align="left" style="margin-bottom: 0mm"&gt;Ce tuto est en cours de rédaction. Toute aide est la bienvenue : comments [at] jujens [dot] eu&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;Vous pouvez télécharger la version odt &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_avance.odt"&gt;ici&lt;/a&gt; et la version pdf &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_avance.pdf"&gt;là&lt;/a&gt;.&lt;/p&gt;
&lt;div id="Table of Contents1" dir="ltr" style="background: transparent"&gt;
	&lt;div id="Table des matières1_Head" dir="ltr"&gt;
		&lt;p align="left" style="margin-top: 4.23mm; page-break-before: always; page-break-after: avoid"&gt;
		&lt;font face="Liberation Sans, sans-serif"&gt;&lt;font size="4" style="font-size: 16pt"&gt;&lt;b&gt;Sommaire&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;/div&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__306_726403024"&gt;1
	La table des matières&amp;nbsp;: fonctionnalités avancées&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__1287_1283162286"&gt;2
	Créer ses styles personnalisés&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3059_1978503572"&gt;3
	Les commentaires&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3061_1978503572"&gt;4
	Les champs&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3179_1136772109"&gt;5
	Renvois …&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</summary><content type="html">
&lt;p align="left" style="margin-bottom: 0mm"&gt;Ce tuto est en cours de rédaction. Toute aide est la bienvenue : comments [at] jujens [dot] eu&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;Vous pouvez télécharger la version odt &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_avance.odt"&gt;ici&lt;/a&gt; et la version pdf &lt;a href="/static/libreoffice/tuto_LibreOffice_Writer_avance.pdf"&gt;là&lt;/a&gt;.&lt;/p&gt;
&lt;div id="Table of Contents1" dir="ltr" style="background: transparent"&gt;
	&lt;div id="Table des matières1_Head" dir="ltr"&gt;
		&lt;p align="left" style="margin-top: 4.23mm; page-break-before: always; page-break-after: avoid"&gt;
		&lt;font face="Liberation Sans, sans-serif"&gt;&lt;font size="4" style="font-size: 16pt"&gt;&lt;b&gt;Sommaire&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;/div&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__306_726403024"&gt;1
	La table des matières&amp;nbsp;: fonctionnalités avancées&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__1287_1283162286"&gt;2
	Créer ses styles personnalisés&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3059_1978503572"&gt;3
	Les commentaires&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3061_1978503572"&gt;4
	Les champs&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3179_1136772109"&gt;5
	Renvois&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__308_726403024"&gt;6
	Les formules et les équations (mathématiques et chimiques)&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1289_1283162286"&gt;6.1 Forme générale&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1291_1283162286"&gt;6.2 Exemples les plus
	courants&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__2982_1136772109"&gt;6.3 Mise en forme&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__3181_1136772109"&gt;6.4 Numéroter ses
	équation&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3183_1136772109"&gt;7
	Bibliographie&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1867_1907339193"&gt;7.1 Constitution de la
	bibliographie&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1869_1907339193"&gt;7.2 Affichage de la
	bibliographie&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__310_726403024"&gt;8
	Notes de bas de page&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__312_726403024"&gt;9
	Format de page&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3162_1880578451"&gt;10
	Les diagrammes et objets OLE&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1871_1907339193"&gt;10.1 Diagrammes&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__1873_1907339193"&gt;10.2 Autres objets OLE&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__314_726403024"&gt;11
	Illustrations&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__3166_1880578451"&gt;11.1 Créer une
	illustration&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__3168_1880578451"&gt;11.2 Table des
	illustrations&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__1293_1283162286"&gt;12
	Métadonnées&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__1875_1907339193"&gt;13
	Formulaires&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__1877_1907339193"&gt;14
	Publipostage&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3661_1880578451"&gt;15
	Références&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__318_726403024"&gt;16
	Suivis des modifications&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__320_726403024"&gt;17
	Les bonus&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__322_726403024"&gt;17.1 Faire des dessins&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__2673_1283162286"&gt;17.2 Exporter son
	document&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__324_726403024"&gt;17.3 Les PDF hybrides&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__326_726403024"&gt;17.4 LaTeX et LibreOffice&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 9.98mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__328_726403024"&gt;17.4.1 L’import&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 9.98mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__330_726403024"&gt;17.4.2 L’export&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-left: 4.99mm; margin-bottom: 0mm; page-break-before: auto"&gt;
	&lt;a href="#__RefHeading__332_726403024"&gt;17.5 Envoyer des documents
	sur les serveurs de l’école facilement&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__334_726403024"&gt;18
	Auteurs et licence&lt;/a&gt;&lt;/p&gt;
	&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;a href="#__RefHeading__3185_1136772109"&gt;19
	Pour aller plus loin&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h1 class="western" style="page-break-before: always"&gt;&lt;a name="__RefHeading__306_726403024"&gt;&lt;/a&gt;
1 La table des matières&amp;nbsp;: fonctionnalités avancées&lt;/h1&gt;
&lt;p&gt;Vous savez désormais insérer des tables des matières. Voyons
maintenant comment personnaliser cette table pour la rendre conforme
à vos désirs.&lt;/p&gt;
&lt;p&gt;&lt;img src="data:image/png;base64,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" name="images2" align="left" width="643" height="339" border="0"&gt;&lt;br clear="left"&gt;Tout
d’abord, vous n’êtes pas obligés de faire apparaître tous vos
niveaux de titres dans la table, surtout si vous en avez de nombreux.
Dans le champ &lt;i&gt;Évaluer jusqu’au niveau&lt;/i&gt;&lt;span style="font-style: normal"&gt;
entrer le nombre qui correspond au niveau maximum de titres
souhaités. Par défaut ce chiffre est de 10, ce qui correspond au
nombreux de niveau de titres par défaut.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Ensuite, vous pouvez changer
l’ordre du texte de la table, en supprimer, &lt;/span&gt;&lt;span style="font-style: normal"&gt;choisir
la partie du texte cliquable qui vous envoie vers votre chapitre…
&lt;/span&gt;&lt;span style="font-style: normal"&gt;Pour cela, allez dans
l’onglet &lt;/span&gt;&lt;i&gt;Entrées&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
&lt;/span&gt;&lt;span style="font-style: normal"&gt;Sélectionner le niveau de
titre que vous souhaitez modifier. &lt;/span&gt;&lt;span style="font-style: normal"&gt;Par
exemple pour ne placer le lien hypertexte que sur le numéro du
chapitre&amp;nbsp;:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p style="font-style: normal"&gt;Cliquez sur FH (fin de
	l’hypertexte)&lt;/p&gt;
	&lt;li&gt;&lt;p style="font-style: normal"&gt;Cliquez dans la case vide à
	droite de E# (numéro de chapitre)&lt;/p&gt;
	&lt;li&gt;&lt;p style="font-style: normal"&gt;Cliquez sur le bouton hyperlien&lt;/p&gt;
&lt;/ul&gt;
&lt;p style="font-style: normal"&gt;Et c’est tout. De la même manière,
vous pouvez déplacer le numéro de page, supprimer le numéro de
titre…&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images5" align="left" width="643" height="341" border="0"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__1287_1283162286"&gt;&lt;/a&gt;2 Créer
ses styles personnalisés&lt;/h1&gt;
&lt;p&gt;Ouvrez l’écran &lt;i&gt;Style et formatage&lt;/i&gt;&lt;span style="font-style: normal"&gt;
(&lt;/span&gt;&lt;i&gt;F11&lt;/i&gt;&lt;span style="font-style: normal"&gt;). Faîtes un clic
droit et cliquez sur &lt;/span&gt;&lt;i&gt;Nouveau…&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="data:image/png;base64,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5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5CORAAAA+UgkAABAPhIJAACQj0QCAADkI5EAAAD5SCQAAEA+EgkAAJCPRAIAAOQjkQAAAPlIJAAAQD4SCQAAkI9EAgAA5COR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" name="images8" align="left" width="479" height="406" border="0"&gt;&lt;br clear="left"&gt;&lt;span style="font-style: normal"&gt;Entrez
un nom pour ce style.  Le &lt;/span&gt;&lt;i&gt;Style de suite&lt;/i&gt;&lt;span style="font-style: normal"&gt;
est le style de texte qui sera appliqué lorsque vous appuierez sur
la touche &lt;/span&gt;&lt;i&gt;Entrée&lt;/i&gt;&lt;span style="font-style: normal"&gt;. &lt;/span&gt;&lt;span style="font-style: normal"&gt;Le
champ &lt;/span&gt;&lt;i&gt;Lié à&lt;/i&gt;&lt;span style="font-style: normal"&gt; permet
de faire jouer l’héritage des propriétés du style parent. Si
vous effectuez une modification à ce style, elle sera appliquée à
votre nouveau style. Le champ &lt;/span&gt;&lt;i&gt;Catégorie&lt;/i&gt;&lt;span style="font-style: normal"&gt;
permet de classer les styles. Ce classement est accessible via le
menu déroulant en bas de l’écran de style.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;Concernant les autres onglets,
ils vont vous permettent de personnaliser votre style. Signalons tout
de même dans l’onglet Enchaînement, l’option qui vous active la
césure automatique.&lt;/span&gt;&lt;/p&gt;
&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;&lt;b&gt;Si
vous rencontrez des problèmes liés au style, sélectionner le texte
concerné puis clique droit et cliquez sur &lt;i&gt;Effacez le formatage
direct&lt;/i&gt;.&lt;/b&gt;&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3059_1978503572"&gt;&lt;/a&gt;3 Les
commentaires&lt;/h1&gt;
&lt;p&gt;Vous pouvez ajouter des commentaires à un endroit du texte. Pour
cela, allez dans &lt;i&gt;Barre d’outil&amp;nbsp;: Insertions &amp;gt;
Commentaires&lt;/i&gt;. Dans la boîte qui apparaît à droite, vous pouvez
entrer votre texte. Les commentaires contiennent le nom du
commentateur et la date. À côté de ces informations, la flèche
vous permet de supprimer ce commentaire.&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3061_1978503572"&gt;&lt;/a&gt;4 Les
champs&lt;/h1&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3179_1136772109"&gt;&lt;/a&gt;5 Renvois&lt;/h1&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__308_726403024"&gt;&lt;/a&gt;6 Les
formules et les équations (mathématiques et chimiques)&lt;/h1&gt;
&lt;p&gt;Même si LibreOffice n’est pas LaTeX et propose moins de
symboles, on peut faire de «&amp;nbsp;belles&amp;nbsp;» équations avec&amp;nbsp;!&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="data:image/png;base64,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" name="Objet1" hspace="8" width="143" height="70"&gt;&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__1289_1283162286"&gt;&lt;/a&gt;6.1 Forme
générale&lt;/h2&gt;
&lt;p&gt;Pour insérer une équation allez dans &lt;i&gt;Barre d’outils&amp;nbsp;:
Insertion &amp;gt; Objet &amp;gt; Formule&lt;/i&gt;. Un cadre apparaît en bas de
l’écran dans lequel vous pouvez taper votre formule. Si vous ne
connaissez pas les commandes, une fenêtre apparaît également avec
les dessins de relations, opérations… En cliquant sur ceux-ci, du
texte est inséré dans le cadre d’édition de votre formule. Bien
pratique si vous ne connaissez pas le texte permettant d’insérer
ce symbole&amp;nbsp;!&lt;/p&gt;
&lt;p&gt;NB&amp;nbsp;: si cette fenêtre n’apparaît pas, sélectionnez
&lt;i&gt;Éléments&lt;/i&gt; dans &lt;i&gt;Barre d’outils&amp;nbsp;: Affichage&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ce texte est composé de deux éléments distincts&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;&lt;i&gt;&amp;lt;?&amp;gt; &lt;/i&gt;&lt;span style="font-style: normal"&gt;à
	remplacer par votre texte (le plus souvent ce sera des nombres)&lt;/span&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;&lt;i&gt;symbole&lt;/i&gt;&lt;span style="font-style: normal"&gt; qui
	schématise l’emplacement d’un symbole.&lt;/span&gt;&lt;/p&gt;
&lt;/ul&gt;
&lt;p style="font-style: normal"&gt;Par défaut, seul un chiffre ou groupe
de chiffre sans espace est concerné par le symbole. Pour que
celui-ci affecte toute une expression, mettez celle-ci entre
accolades. Vous pouvez également utiliser des parenthèses, mais
celles-ci apparaîtront dans la formule.&lt;/p&gt;
&lt;h2 class="western" style="font-style: normal"&gt;&lt;a name="__RefHeading__1291_1283162286"&gt;&lt;/a&gt;
6.2 Exemples les plus courants&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;Les fractions&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACcAAAAmCAIAAADInRXHAAACBElEQVR4nGP5//8/A90BC/2tHGq27j94aMLkKRvXrKKTrd++f5+3YKGIiPDjJ0/Is5IcW7k4OXMyM4CMrt5++tlKFTBq66itI87W12/eVNTU3n/wEMh28vBSUlTobG0RFhKira2iIiJzZ0wnVReltlIFjGRbjSysaGTTuRPHcNpKH4BuK7KL6GcrfcCwsDU6IenZs2fAVg6wMHFycMhISwG2PWhu679/f5ctWgC08sOHj9Nmzerq7Wuoqaa5rcsXLYQwgM25gtwc/5AwrMqw23rp8pXs/AJ3V5eaygog98KlS6WV1bu3bkZWA8zZ+BM8IwMjEJBgq56uTl9XZ2FpWVFBPicHx+EjRxtrsQQUfnD/wQM9HR0SbAUCUxNjZWWlDRs33bpzx8vd3czUhFRbN2zenBAXQ5qtQJCSkFBYVr543hxNDQ24IHKRCWdjBvWBQ4clxMUN9PRIsxWY+nfu3iMkJPjm7TtkcbgFeOL1xKlTFy5eBKYmXIZjt/XZ8+fzFi7KTEvVPqo1d8ECW2sSqoS9+w9cuXYNj5XYbb1+48bR4yeqykqZmJh8PD0nT5t++sxZYDQTY+Wadeufv3iRn52FXxkWW/OKS2dPmwK0Esjm5eXxcHMtKC3ramuxtrREVoY1eNu6uoHk/EWL8SvDYitavqyrqgQi/G7HbwdRttIBjCRbAfp5vKN39LFKAAAAAElFTkSuQmCC" name="Objet4" hspace="8" width="39" height="38"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;1
	over {x + 2}
	&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAnCAIAAADCRozOAAADYUlEQVR4nGP5//8/w+ADLAPtAOxguDtr/8FDEyZP2bhmFVVMo4Kzvn3/Pm/BQhER4cdPnlBuGgRQwVlcnJw5mRlARldvP+WmQcBwT1vUBaPOIgWMOosUMHyd9frNm4qa2vsPHgLZTh5eSooKna0twkJCA+wsURGRuTOmU24OMhi+kUgLMEScZWRhNSDuAIJzJ47B2UMktJCdPIAAZ2hduHTJQE+PdhYfP3HS0sIclyx2Z929d//Jk6c0ddbzFy9u37mjqqJCgrOWLF9eU1FOOzcBgZ+Pd01DU0dLE1ZZLM568PAhMxMTMzMzVayPTkh69uwZsL0PrAycHBwy0lKAjWyQxSwsnJwcwOa/rIwMUc46euy4jrY2VdwEBP/+/V22aAHQTR8+fJw2a1ZXb19DTTVESldH5+DhwzGRkUQ5C5jYY6KwKCUPLF+0EMIAdo0KcnP8Q8LgUkoK8ivXrMWqC4uz7t1/ICEujiZ46fKV7PwCd1eXmsoKBrDTSyurd2/dDFcALIcJFi6MDIxAAOdKSkrevnOXWGd9+vyZi5MLTVBPV6evq7OwtKyoIJ+Tg+PwkaONtdX4HYEJ7j94oKejA+dycnJ+/PiRWGd9/vQJmBgxxU1NjJWVlTZs3HTrzh0vd3czUxNSnbVh8+aEuBg4F5j2P3/+TKyzGJDCGQ2kJCQUlpUvnjdHU0MDIoJch8LZWGPzwKHDwLSBXBaCBotw2IXFWby8vN+//+Dl5UETB2bynbv3CAkJvnn7Di4IdwH+tHXi1KkLFy8Ckzyy4PcfP/j4eIl1Fj8f37fv39Cc9ez583kLF2WmpWof1Zq7YIGtNQkNjb37D1y5dg3NTSBnff/Ox8tHrLOUlRRfvHwpLiYGF7l+48bR4yeqykqZmJh8PD0nT5t++sxZYFIjxk1r1q0H1jP52VmYUkBxoF3EOstAX//+/Qf6urpwkbzi0tnTpgDdxACKYh4PN9eC0rKuthZrS0u4Glwx2NbVDSTnL1qMqRKYMfVxVLtYnGVjZblo6bIAP1+4CHL5BAR1VZVAhNU4TIAnwV29ei0mKopYZwErKWCh9/fvX2pVi1gB0HxgRlSQlyPWWUAQHRG+c88eYOFEO2ft2LU7JioClyx2Z8nLyX3+8oVmToJYIauooIBLFgCNKjFqPUmxiAAAAABJRU5ErkJggg==" name="Objet5" hspace="8" width="50" height="39"&gt;1
	over (x + 2)&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;La puissance&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAUCAIAAADtKeFkAAABOElEQVR4nGP5//8/AwWAhRLNJOgPiYx+8vSpoKBgZmqKn483yfq5uLgO7d19//6D1KxscvQvmjsbSIqICAsJCiKLk+b/7Tt3lhQWkKl/9959ejq6ero65OjfvHWbuJgYmmYS9Nc3t8DZ504cw6f/0uUr2fkF7q4uNZUVQO6FS5dKK6uR9RCwH+jIvq7OwtKyooJ8Tg6Ow0eONtZW43IXdvebmhgrKytt2Ljp1p07Xu7uZqYmpOkHgpSEhMKy8sXz5mhqaOBSg1P/t+/fd+7eIyQk+ObtOzyaset/9vz5vIWLMtNStY9qzV2wwNbaigT912/cOHr8RFVZKRMTk4+n5+Rp00+fOQsMDmL15xWXzp42BagZyObl5fFwcy0oLetqa7G2tCRK/+6tm5G5dVWVQESC+0kFlOoHANCvaz1wg8XOAAAAAElFTkSuQmCC" name="Objet6" hspace="8" width="21" height="20"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;x^2&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Les indices&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAUCAIAAADtKeFkAAABTElEQVR4nGP5//8/AwWAhRLNo/qx6b90+Up2foG7q0tNZQWQe+HSpdLK6t1bNxOrX09Xp6+rs7C0rKggn5OD4/CRo4211STYDwSmJsbKykobNm66deeOl7u7makJafqBICUhobCsfPG8OZoaGrjU4NT/7fv3nbv3CAkJvnn7Do9m7PqfPX8+b+GizLRU7aNacxcssLW2AgrevHW7tLLqP8P/vs4OVRUVnPqv37hx9PiJqrJSJiYmH0/PydOmnz5zFhgcU2fMyMlM//79x5QZMyf2dOPUn1dcOnvaFKBmIJuXl8fDzbWgtKyrreXKteudrS1///6dNHUaPvejxXNdVSUQARlfvnzh4OAAZtbPX74Q8D9WwMvD8/3Hj79//vLx8pKjX1tL88jRo0D/a2trkaM/KyO9pLySkYmxt6ODHP0aampb1q/FFKc0/wEAhdWDcgaqigkAAAAASUVORK5CYII=" name="Objet7" hspace="8" width="21" height="20"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;x_0&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;La somme&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAsCAIAAAB+JKZoAAAEf0lEQVR4nGP5//8/wyAALAPtACjA7o4XL14WlVcsWzj/5q3bpZVV/xn+93V2qKqooHFp647HT57Mnjf/xs2bQPbUGTNyMtO/f/8xZcbMiT3daFzaukNWRqaprnbLtu1A9pVr1ztbW/7+/Ttp6jRMLm3dgQy+fPnCwcEBTMufv3zB5NLPHbw8PN9//Pj75y8fLy8ml37u0NbSPHL0KDBBaGtrYXKJAfsPHpowecrGNatIdsf5CxdrG5uADJ/A4OjIiElTpzMyMfZ2dABFsjLSS8or4Vz84Nv37/MWLBQREQYmfIKKsbjD0EB/y/q1cG5kWCicraGmhiyFH3BxcuZkZgAZXb395LhjQMAgdod3QNDzFy+I0ZyXnZUQG0Mrd0zs7U5MTf/67Vt7c5O7qwumgl+/fgEL+I6e3itXr1HFEdjdoaKs3NbUWFhWXt/cIi0lqaOtjaaAjY1NV0e7ub42K6+Ahu4AAlsb64Lc7L6JkwtLyxfPmyshIY6pRklRccfmjbR1BxDEREbeu/9gw6bN+SWl82fPBGZCallJmjuAoKqs9PHjJ2fPn6+srevv6mRiYiLJ6Ndv3lTU1N5/8BDIdvLwUlJUANaRwkJCJLuDhYWlp7M9NjH58JGjfZMmlxTkk+QOURGRuTOmE6mYQPnBz8c3qa8nLjl12YqVivLywYEBJDmFeEC4HFOQl+9qa8ktLO6dOMnNxYWXl2dg3AEEFmZm9ra21lYWNHIEse7YsWu3pKREoJ8fQZVGFlYkWX/uxDFi3XHt+o3d+/Z1t7WSZAGpgIA73rx5O2natJ72NiIzLdx/1HQHsB5paGmtLi/j4aFCsgiJjH7y9KmgoGBmaoqfjzcJ7mjr7I6PiQY233EpePnq1YzZc+qrq4hxBxcX16G9u+/ff5CalU2COxYsXqKlpWlqYozH6OmzZgO9SIwjgGDR3NlAEthMFBIUxJTF7g5gAQr0a3lxEVbZX79/P3r0aNHSZcA+DjDAiHQHBGzfubOkEEstjcUd9+7fr6qrB7Y/Vq5eQ9BcYAOAeEfs3rtPT0dXT1eHKHcAK1igI4g0GrN1ggts3rpNXEwMqyOwu2PzWsLBQAYAtqrgbMzsTZN2MrAmAtaLi+bOWbB48bETJ4EMZSVF/EULTdxRnJ+3c/fuZStXArth6SnJOYVF2zeux6+FTHfAB0iwyn76/PnHj5/5OdlioqIfP35kZCRsIDnuQB4gwQru3r2nrakJdASQff/BA2VFJdLcAWxk/Pv3F8gAtnecHByADEd3T6CH4ApkpKU3rV2NPECC3R337gFbgTD2fRVlEt3h4+W5fNWqiNDQnbv3QtyxfydOy/CAO/fuqSorw92hpalBmjtu3rrl7Oj49etXNVWKxr7u3bvv5uwMZT+47+fjRaI7bt+OjYrcf+CQjTW0OYM1XggaihYvpZXVS+bP5efnJ9Ydt27dVlVRmTl77vMXz23BTsEaL8gDJM31dYYG+mgK9u7YBmfv3rqZoLvR3bF72xYgCew14deDNkBCFTCIxx0GBAAAMon8TWrwpssAAAAASUVORK5CYII=" name="Objet2" hspace="8" width="45" height="44"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;sum
	from n = 1 to 100 {1 over n^2}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;L’intégration&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEcAAAAnCAIAAADSJsISAAAEsklEQVR4nGP5//8/w7ADLAPtAJoAfL66eet2aWXVf4b/fZ0dqioqdHMT5QCfr6bOmJGTmf79+48pM2ZO7Ommm5soB/h8deXa9c7Wlr9//06aOo1uDqIKwOerL1++cHBwAIuTz1++0M1BVAH4fMXLw/P9x4+/f/7y8fLSzUFUAfh8pa2leeToUWC+0tbWopuDqALw+SorI72kvJKRibG3o4NuDqIKwOcrDTW1LevX0s0pVAQjrxYeuoAoX924ebOhpfXho8ee7m51VZW0dhPlgLCvfv78WVhW0d3e2trReffePTq4iXJA2Fd79u1nZGTQ0dJavmghHRxEFUDYVydPn2ZjZaODU6gICPvqzt17v37/ooNTqAgI++r169d///2jnQuiE5KePXv27ft3URERJweHjLQULk5OTGXXrt8oLq8QFRVdNHc2QTMJ+wrYtGViYiLHvcSBf//+Llu0AOilDx8+Tps1q6u3r6GmGlOZlqZGa2PD9l27iDGTsK9+//7NCCwuaAbghZCIiHBBbo5/SBgulafPnlVXVSXGTMK++g8GBJVdunwlO7/A3dWlprICyL1w6VJpZfXurZvhCowsrM6dOIbfEEYGRrQQBNYrM+fM3b5r9/v371mYmadPnkTQIqJ8RSTQ09Xp6+osLC0rKsjn5OA4fORoYy2WhIQf3H/wQE9HB84FhmZReYWxoeHyhfN//PgZk5ikqqIM7PIRtIiaLSZTE2NlZaUNGzfdunPHy93dzNSEVBM2bN6cEBcD527fCcpFSfFxQPL79+8CAgJALxFjEZXbgSkJCYVl5YvnzdHU0ICIABMeXBbOxpoUDxw6LCEubqCnBxfZvHVbdGQEhH37zl0VZWU8FiEDavoKWDrv3L1HSEjwzdt3cEG4B/DnqxOnTl24eBFYWiAL3rh1C5iwIexbt2+rq6nisQgZEPYVsFhnZmYmqOzZ8+fzFi7KTEvVPqo1d8ECW2srglrgYO/+A1euXUPzEhD8+PGDjZUVwr55+7ajvR2RFhH2FbDkYedgx6/m+o0bR4+fqCorBQaBj6fn5GnTT585C0z9xHhpzbr1z1+8yM/OwpRSUVZat2FjgL/fxs1b9uzdl5GSTKRFhH0F9JKIsAh+NXnFpbOnTYFU1ry8PB5urgWlZV1tLdaWlnA1uJJfWxdopHH+osWYKgtzc6sbGpevWl1WXAQs85vbO69ev07QIuJ8xc4uKyODXw1adQHsgxHfDcOT2YwMDbZvXA9h79+5HVMBLosI+4qZmcVQX4+gskEFCPjq79+/nz59cnd1pY9rqAWw+yo8Jg7YcJkzfRqwtAkOCJCQEKezsygE2H0lJytz6MjR0KiYoAD/5IR4OruJcoDdV93tbVjFHz95kpyRKSMt097cKC4mRkuHUQSIalsAW5CtnV0a6upysrKtDQ3AGrO7b0JPB3afDwaA7itHd8+PHz/CuTLS0pvWrm7p6OztbP/37//chQuLTHI1NdQXLF7MMIgBuq+wVgvAWu/Xr99v370D9n9evX796PFjHm4eujiPTEBUCqytqqhramZhYZk6oT8jJxcYac31dbR2GSWAKF9ZWVjApxHWrVxBS/dQBwAAhk7zLzTGQTQAAAAASUVORK5CYII=" name="Objet3" hspace="8" width="71" height="39"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;int
	from - infty to 0 {x + 2 dx}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Les lettres grecques&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAAQCAIAAAAnLJARAAADFklEQVR4nGP5//8/A1XB6TNnO3p6X716ZWlhXlNZwcfLS13zWahr3Os3b9as3zB98kRmJqam9o6+iZMaaqqpawWVXbxl2/bE+FgxUVEgu6ywMD4llbrmM1DdxQcOHYoIDYGwRUVF/lE7yTFgdfGNmzeBCfH2nbuO9naNtTVfvn79/u27hIQ4mjIjC6tzJ46hCb548ZKTkxPCPnHqVHpyElZbseo9f+Hik6dPnZ0cuWAmfPr8efnKVZbm5nq6OjhdDNSTmpWjpKiwcfWqS1cub92+49iJk7du3163cjk+j8PA23fvfv78GRAWERIYwMLMHBYSTIwuIPj379+ly5d37N49Y/acWVOnSEtLAQWBuXbthg18fHz4XDxj1pyvX79mpqWKiAg7OTisWrMW6G47GxviLWZnZ9++cT2Q/e3799aOrqiIcC1NDYIamZiY4mNjoiMj4lPSKmvrFs6dzcjI+OfPn18/fzna2SGrRHfxsZMngaSmBtQODg4OYETb2VjDFQAjFJONGcVAAIxcoBMaW1qXL1pIpF4WFpbcrIysvIITJ08BC8cjx44H+vuhJUh0F3/58gViGczF7FKSkhZmZnAFcAuwpkU0oCgv/+jxE5L0Au1SkJffvG2bhbnZ7r1766oq0RSguxiYgm/dvvPs+XN5OTkg9+jxE4H+vsAow+8yXODho8eyMtKk6nJ3dVmyfMXqteuA2QCYxgi4ODUpqbSyavqsOVXlpTdv3rp67TowjO/dvz9xytSJvT3E2Lf/wMHPX74AbQV6u7WzMzIsjFQXu7k4z5wz99Hjx1gzLrqLnR0dOltbZs2d6+rlo6aq0tPRBtQZm5Ti7+ODphJXtDrY2wG95+7jB8w6EWGhfj7emGrwJ6dLl6/w8/EB0zRWWSyirs5OQATnAlPV0f178ViABoAOLcjNASLitSCDOfMXAFMmMIrevH2LVQGV6zwKwYcPH759+wYsVXfs2i0vJ49VDZVdrKykSIl2Lm7uBw8ftnf1XL5ytTg/D6saKrt49bKllGhnY2UF5qL7Dx4W5edilhIQAAAn80BB/filqgAAAABJRU5ErkJggg==" name="Objet8" hspace="8" width="59" height="16"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;%alpha
	+&amp;nbsp;%bêta + %gamma&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Les vecteurs&amp;nbsp;:&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAWCAIAAABVH8vfAAABo0lEQVR4nGP5//8/AxHg6bNnUpKSjIyMuBSwoPHff/jw5csXTHUrV6/ZvXefrY21vY2NmakJOzs7AYO2bt9+5NhxTIPevXv3+s2bdRs2Hjx02NnJMT0lWVBAAJ9BMZGRQIRp0ILFS378+GFjbaWtqYnVg+gG4QIJsTH4FWAx6PjJU1V19R8/fkQTFxYS2r1tCwkGWZqbxcdEf/36NTsjHcj9+/fv79+/b9y6NXvuPNJcBAS3bt92sLOFsJnBgJODU1VFhWSDbt+5k5qUiCyirqYKRKQZBPTIixcv5eXkINxPnz+nZmavXLIIjynYDbp3/8HXb99MrGzgIpYW5vhNwW4QMIB8vDyb6moh3GMnTpw5e44cg27fuYscrlYWFkBEnkF3rCzR/VJd39Da2ABkAIOvqLxi2cL5RBkEdxGwbACG/clTp//8+QvkPn7yZPa8+Tdu3iTgImB2be/qfvf+vauXD5q6koJ8ICkrIwMMuy3bthMwyMbKcuuGdZiKiAHEZtrBatD5CxdrG5uADJ/A4Ob6OkMDfTINAurcsn4tFVyEBwAAfNupMnxZx1sAAAAASUVORK5CYII=" name="Objet9" hspace="8" width="24" height="22"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;widevec
	{E_1}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;
	Le saut de ligne&amp;nbsp;: newline&lt;/p&gt;
	&lt;li&gt;&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;
	Les systèmes d’équations&amp;nbsp;:
	&lt;img src="data:image/png;base64,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" name="Objet12" hspace="8" width="90" height="63"&gt;&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;left
	lbrace stack {x + y + 2 = 0 # x^2 + y + 7 = 0 # 3*x + y = 9} right
	none&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;
	Les matrices&amp;nbsp;:
	&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;left
	[ matrix{1#0##0#1} right ] nitalic{ et }&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt; &lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;left
	[matrix{A_11#A_12#dotsaxis#A_{1n}##A_21#{}
	#{}#A_{2n}##dotsvert#{}#{}#dotsvert##A_{n1}#A_{n2}#dotsaxis#A_nn}
	right ]&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;p style="font-style: normal; font-weight: normal"&gt;&lt;img src="data:image/png;base64,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" name="Objet10" hspace="8" width="200" height="92"&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;
	La chimie&amp;nbsp;:
	&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJEAAAAYCAIAAAB1BYhkAAAEXUlEQVR4nGP5//8/wygYUoBloB0wCkgGo3E29MBonA09MBpnQw+gxNm58xdqGhtfvHgpISHeUl9vZGiAKYLHrH///q1Zt379pk0PHj4CcpWVFEMCA/19fRgZGcl2HyVOooV7gCA6IenZs2ffvn8XFRFxcnDISEvh4uSk0KkkORglzoCGbtuw3sjCCkjiEsEF/v79W1RewcPNXV9dpaigABS5/+DBwiVLj5881d7cyMTE5Oju+fHjR7h6GWnpTWtXEwwgsp1E0D0ErcYF/v37u2zRAmCEffjwcdqsWV29fQ011ZQ4lVQHU61sXLV2HQc7R2tjA1xEQ129vbmprKp63YaNIUGB+3dup5ZdVHEPfu37DxwUFxfX0tTAlFq+aCGEISIiXJCb4x8SRmcHUy3OduzaVZCTgykeERo6ZfoMgmEEBMD0eO7EsUHiHn19vZz8wu6ONmkpKTzKGBkYKSxp4YB4B1Mtzu4/eCgnK4MpLicre/f+PWrZQl33AOuPE6dO4TLB1MQ4Iydvcn+vgrw8blse6OnoUO5aBlICEHucAZM8qVZ++/aNj48PU5yfn+/bt++kmka5k4hxz58/f3IKivCbE5OQlJeTHRYchFV2w+bNCXExFDoVAogPQOxxhlZGEeMIYOX54eNHYM2MJv7+wwegFB6NyIbD2ZiFJKlOIsY9bGxslJTGBw4dlhAXN9DTo9CpEEB8AFKtbFRRUX746BGmlQ8fPVZWVsKjEe5D6tZnxLgHf9kIB8CmvIG+PpogUOOFixeBbRCquJaBlAAkOc6CwiOePH0mLibW0dKsraUJF/f29Fi+arWJkRGa+uUrV/p4epJqC0kgJDL6ydOngoKCmakpfj7exLsH2ID++/dfa0fnq9ev8ZgP7CetXrYUWWTv/gNXrl0jNcKwuhMOiA9AkuNMTExsxeJFN27eamxtXbV0CVzc38fn5KkzFTV1wPJdEVxpA+vn+YsWc3JyAnuFpNpCEuDi4jq0d/f9+w9Ss7LhYUGke2ytrRbPn5udX1BckG9uakqMdcBu7/MXL/Kzs6jiTjggPgBR4uz8hYu1jU1Ahk9gcHN9naGBPqbIjMmTgFX39x/fWVnZkPUC0yyw67dx85bmto579+8DRZQUFcNDgjEdhwtgLRiJcdKiubMZwL0lIUFBMtwDLI4m9/cVlVVM6lUSFhYm6M62rm4gCQxNNJcTdCpWd5LhYJQ4A1qzZf1a/CJAYGZjB/TbhO4uNHFgTyXAzxeICHqbeECkk4Bg+86dJYUF5LkHWNQ31tb8I24qEVelS6RTMd1JqoPJaYOcOHzw7LnzVXX1G9esIkM7LcDuvfv0dHT1dMnvKqngbShRC1DuTgYy4qysqrqtqZGVleXzly+UWExFsHnrNmBGoTAg6ACo5U6S4+zBw0dWDk7AsrGsqJBCu6kF6ptb4Gwq9haoDqjlTpLjbNXSxYQV0RcM5nhCBtRy5+ic59ADo3E29MBonA09AABF3r7n1xYoyQAAAABJRU5ErkJggg==" name="Objet11" hspace="8" width="145" height="24"&gt;&lt;/p&gt;
	&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;nitalic{&amp;nbsp;H_{3}O^{-{}}&amp;nbsp;+&amp;nbsp;H_{2}O&amp;nbsp;%Ux21CC&amp;nbsp;2H_2&amp;nbsp;O}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p align="left" style="margin-bottom: 0mm; page-break-before: auto"&gt;
	Les autres caractères spéciaux&amp;nbsp;: vous disposez d’un
	catalogue de symbole à votre disposition via le bouton
	&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAEk0lEQVR4nLVWa0xTZxg+PT3toA1YoGClKaNQICKM6iqTCYsuszIljhnUOHbxti3MbPjLHzNbTNZsyXTEzUxNhos4zQhO2cQ0bBrJ2AJeGAyUAdZmgw66BkuJsBbobU/7wWl7eth+2L05aZ/vct7nvX3v+Ri73U79n8L4/X6BQAAEYBu3WW1Wp9MZK+0SiYSBUkWaAgOACceEtlCbkpwSKwL7hJ2x/mUlBLA9ttoh0MY4XfMBQWQwRqBiSABhwgf+oMSYgGQYwoJw8S0wYlHAtwWrfiq0h47awUS9MO/B16295409g3+MA5euzNxYklu5Ll8sEgqFNLu5+Xp/c1t/R+8wsEohO7R3/XJ1WnpqYjgLE7CMeEAJWALjz0MnL9w4uOuZ4hWq1CTphprTZ690O2fm9ryg83i8hAOqTzff/nvGbTy+KydD3nT1zsFjxg/e0qenJoSHmaFYNkEoB19culW9SbtpbR6h/OHEntzKT77vNO3e8iRNC3w+PzF/aPjBlc9e06gCpbHtuQKzxf7xmR+fX5tLQkf84Pfgrtlm2K/nJLx7YJSdQW46+0YAclShwitbmfnld13skPxzq4jFjocuanHhrTXXrDt6MiJErJRqH3/v5NVT71bmZATOHYLDec3r9RFQ/23XvkodwC8Do4b667p8ZRQB17SAbfXvb62oPVtR28DO64oL75uG816sA5YlJSYkSHNy1aZ7vx9paMdD9iyTJ5wzbOcENiIH4Qet5dgr1YeaugfHyBDaJx0PCQbAAxpguUxK00R7YuNHO6LPKX8VETln2Mbi/KpP8fvbN7Wcmfb6fRzvuQSLecAr0av/2Vq4OeCIL9gKPF4fAsKGiEj0DD9BeC/ieED6TKjXRNqLPIMgdDJw+vj61aLd9HL7YGuH6aeeYTIkVVT6ZgNJ71KFHI9lxFqw/TjZUPKEasNT2RVlefGPiSI94MtBS/vQ5xdujo1Psfu6bt1hMakiTig6+yzmPyecM+5XN2sjPeA7aK2dJrh66chOjSoZwzMtPXXnOwD6GvezvhbtPAFQU7W6pqoYwDRif+eo8dpNMyEI9SLeECEyRw/o1elLPB4PhtXlBYTA7eY2g71btHNzcwBZStnhN9a9brhMNKA66KDJ3GZHLWRSkSzFm16vF0Ofb74xsBeOmYW2Mz09DV9pmsaHQiQMzMAmYJQGJYgKEfEAZhZq0vrujSlkDHaDw2ILRHzNiqUOhwPAG/zOFWlSeu/bfx0YgaMMw0Bp221ztlIGs8RiMSh5uiksxZtQWvF01qnmntnZ2Yw0iYgRfPhVt1Iuqd263OVywV7yPVidl/Jg0oWll/XZ0jjxqN15sc18YMcqEEC7SDRfS/xVVF6SxQipxmuDJsskhgXqpMO7deSKBhEygZ3rV6ncXupGv62u6S72qJclvl2lLStS+heEp4rIAlSAX79G86wu0xcUKuyI0TTNpuqljUuqywtJDsgBI7YH4+Pn9yAwxQTuk8gatka3GvaeSU4+y8oaRweFPdD8ZYplZI16BAnz4F/vRY8uTFxcHEHx8fFTU1O4D8eW4B/bsI+Ok94qNwAAAABJRU5ErkJggg==" name="images6" width="32" height="32" border="0"&gt;.
	Si la liste ne vous convient pas, vous pouvez ajouter d’autres
	caractères (dans le jeu de symboles Spécial de préférence) via
	le bouton insérer. Vous pouvez également utiliser directement le
	code UTF-8 si vous le connaissez.&lt;/p&gt;
&lt;/ul&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__2982_1136772109"&gt;&lt;/a&gt;6.3 Mise
en forme&lt;/h2&gt;
&lt;p style="font-style: normal"&gt;Il est tout à fait possible de changer
la taille et la fonte d’écriture de votre équation. Pour cela,
cliquez sur l’équation à modifier et allez dans &lt;i&gt;Barre
d’outil&amp;nbsp;: Format&lt;/i&gt;&lt;span style="font-weight: normal"&gt; et
choisissez le sous menu que vous désirez (&lt;/span&gt;&lt;i&gt;&lt;span style="font-weight: normal"&gt;Polices,
Tailles de police)&lt;/span&gt;&lt;/i&gt;&lt;span style="font-weight: normal"&gt;. &lt;/span&gt;&lt;span style="font-weight: normal"&gt;Les
modifications seront localisées à l’équation courante à moins
que vous ne cliquiez sur &lt;/span&gt;&lt;i&gt;&lt;span style="font-weight: normal"&gt;Par
défaut&lt;/span&gt;&lt;/i&gt;&lt;span style="font-weight: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-style: normal"&gt;&lt;span style="font-weight: normal"&gt;Vous
pouvez également &lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: normal"&gt;&lt;span style="font-weight: normal"&gt;apporter
des modifications de style locales. Pour cela, il faut utiliser la
commande &lt;/span&gt;&lt;/span&gt;&lt;i&gt;&lt;span style="font-weight: normal"&gt;size.
&lt;/span&gt;&lt;/i&gt;&lt;span style="font-style: normal"&gt;&lt;span style="font-weight: normal"&gt;Vous
pouvez indiquer une taille absolue ou relative&amp;nbsp;:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAASCAIAAACvlquLAAACLklEQVR4nGP5//8/w0ADloF2AAgMO0dExsU/ffb8+/fvIsLC1pYWuVmZ/Pz89HYEEKxYvFBMVPTjp08zZs9pau/o7WintyOWL1oIYQgLCQGDwTsgiEiNWBxx6fKV7PwCd1eXmsoKIPfCpUulldW7t26GKzCysDp34hh+c//+/SsuJka+I/R0dfq6OgtLy4oK8jk5OA4fOdpYW02kcUDw+/fv12/eAKMjITaGfEcAgamJsbKy0oaNm27duePl7m5makK8I8xt7RkZGeNjon28PClyBBCkJCQUlpUvnjdHU0MDIgKMBbgsnI0ZLycPH3z46HFze/vW7Tu8PT3g4nPmL9iwafOW9WsfPX4cn5y6f9cOAo749v37zt17hIQE37x9BxeE24c/TbCysqooKyXExGzZvh3ZESmJCavXrvv69euHDx+DAwOQtWBxxLPnz+ctXJSZlqp9VGvuggW21laYaggDRkZmZmY0MQ0N9dt37mzeur20qACfI67fuHH0+ImqslImJiYfT8/J06afPnMWmESIsbe4vAKYofh4ed+9f3/uwgVba2s0BVoaGouXLQ8K8Ofg4MDniLzi0tnTpgBdAGTz8vJ4uLkWlJZ1tbVYW1rC1eCKi/fvP/gGBv/6/VtcXCwkIMDX2wtNgaaG+r37D5CNwu4I5PIACOqqKoEIq5WYYN6sGXhkn794sf/gofKSIkwpOlVgnv6BvDw87c1NQoKCA+aI7RvX45EdFFU5ABOG0pO4yJYSAAAAAElFTkSuQmCC" name="Objet13" hspace="8" width="44" height="18"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;x
+ 3 size 8{y}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAUCAIAAACyFKxoAAADdElEQVR4nGP5//8/w1AGLNQ1bv2mTc1tHVilODg4hIWEVFWUnR0dPdxcmZmZqWIjlT3g7+NjaWa+aOmyFatXQ0RWLF6koqz0/fv3p8+eHz56dO6ChQcOHV6yfPmU/j5hYWHKbaSyB5iYmCQkxDPSUuAeUFNVAZLc3NxABhBJS0lV1dXfvHW7vbu3p6ONchup7AEI4OPlxSVlZ2sDYZw4eZIqdtHEA3jAv79/IQwRERGqGEhvD+zau48BnNJyszKpYiDNPfD+wwd+Pr5v3749evxk34EDS5YtNzI0yMnMMNDTo4r5NPeAs4cXMldLU8PRzk5SQoJa5mPxwI2bNzt6em/fuetob9dYW/Pl69fv374DyxY0ZUYWVudOHCNowc4tm0RFRH79+vX6zZtr12+sWbeud+KkiVOnxcdEZ6WnMTIykmEmPg88efo0NStHSVFh4+pVl65c3rp9x7ETJ2/dvr1u5XKSzIUDUXBmZWNjAxagQOTi5Fjf3LJl23ZghcDFxZUYF0uesTg9MGPWnK9fv2ampYqICDs5OKxasxboDTsbGwqtgQNgkKckJgA9AGSvXreOeA98AOYlfn5IjH36/PnHjx9ioqJYPHAMXDxramhAuMD6/8WLl3Y21nAFwFjGZJMU7/AM8O7tOyLN/PjpU31LKwszc28nqJ2yYdNmYBMOmAixeODLly9AkouTE+YBdilJSQszM7gCuLlkpFcIeP7iBYQhJSVFpJnAcqyzpdnGyQWYOoBOf/r0WXlJEUQK3QPA1H/r9p1nz5/Ly8kBuUePnwj09wUW2yQ58fPnL3hkgakfwggJCiTeTGBa4OTgAJq8/9Ch4sJ8uJPQPZCalFRaWTV91pyq8tKbN29dvXYdGAP37t+fOGXqxN4egtYAg+ft23cLly6Fi5w5d87IwADkqy9fgKUQsI10+MhRYFKODA+LDAsl3gNA8Ov372MnToQGBbKwIJyN7gFnR4fO1pZZc+e6evkA217A9tajx49jk1KAzUw0lVjjesPmzWjN6bSsHAZw1QssiAQE+GWlpYGZ2MvDXUFeHlM7njR5/sJFoAkBfujJAUs94OrsBERwLtCmo/v34jIXDQT6+QERkYqJBMBY3bx1Gz8/n5WFBWZipndbiAxw89YtYL4/dfpMQW42puwQ8ICGujofH5+4mBjWThwAdGRV9wp21CIAAAAASUVORK5CYII=" name="Objet14" hspace="8" width="64" height="20"&gt;&amp;nbsp;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;%alpha
+ size *1.5{%BÊTA} + size /1.5{%igamma}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;Vous pouvez également mettre de la couleur avec la commande
&lt;font face="DejaVu Sans, sans-serif"&gt;color&lt;/font&gt;. Vous pouvez
choisir parmi les couleurs suivantes&amp;nbsp;: white, black, cyan,
magenta, red, blue, green, yellow.&lt;/p&gt;
&lt;p align="center" style="margin-bottom: 0mm"&gt;&lt;img src="data:image/png;base64,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" name="Objet15" hspace="8" width="89" height="18"&gt;&lt;font face="DejaVu Sans, sans-serif"&gt;&lt;font size="2" style="font-size: 10pt"&gt;color
green AAUIE {color red bépo}&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__3181_1136772109"&gt;&lt;/a&gt;6.4 Numéroter
ses équation&lt;/h2&gt;
&lt;p&gt;C’est sans conteste une fonctionnalité très appréciable mais
cachée. Démarrez une nouvelle ligne. Tapez &lt;b&gt;nf &lt;/b&gt;&lt;b&gt;(en
environnement français) ou fn (en environnement anglais)&lt;/b&gt; puis
appuyez sur la touche &lt;i&gt;F3.&lt;/i&gt;&lt;span style="font-style: normal"&gt; Le
cadre ci-dessous va alors apparaître.&lt;/span&gt;&lt;/p&gt;
&lt;table width="100%" cellpadding="4" cellspacing="0"&gt;
	&lt;col width="228*"&gt;
	&lt;col width="28*"&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;td width="89%" style="border: none; padding: 0mm"&gt;
				&lt;p align="center"&gt;&lt;img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAAAUCAIAAAC4SAI6AAAC7ElEQVR4nGP5//8/wxABLAPtABLAoHNrSGT0k6dPBQUFM1NT/Hy8kaUGnVu5uLgO7d19//6D1Kzswe7WRXNnA0kREWEhQUE0qUHnVgjYvnNnSWEBmiAWtx4/eaqqrv7jx49o4sJCQru3baGV65DA7r379HR09XR10MSxuNXS3Cw+Jvrr16/ZGelA7t+/f3///n3j1q3Zc+fRwaGbt24TFxPDdCgDrjRw6/ZtBztbCJsZDDg5OFVVVGjoRhiob26Bs8+dOIYshd2tt+/cSU1KRBZRV1MFIpJsnThl6uJlyxfOmb185aqDhw831tWYGps0t7cfP3Gyr7vL1NgIouzrt29Albv37P3565eOlhaa+wi4FRjjL168lJeTg3A/ff6cmpm9cskiCPfk6dOZuflYzWJiYjpz7Aicm5+TvWP3nnkLF4aFBCfExVTVNezcvTckMDA5IaG7v9/UeBpQzZ8/fzJz8izMzbasX/vjx4+JU6fh8TwWt967/wDoVxMrG7iIpYU5nG1uaorH68gAmOLfvn2bmZamoqz09t27Bw8ftjU1AtnvP3z4++cvRM26DRuBxVNWehqQzc3N3VRXS5pbgYnVx8sTru3YiRNnzp4jxnFo4M69ewZ6ekDHAdn3HzyAsx88eKispAhRs3XHjpzMTCINxOLW23fuImcjKwsLICLDrXfv3lMGOw4I7t27D2ffvQcUV4awgYGtAhMnz613rCzN0QSr6xtaGxsYSEmvd+7eU1JUgLnvvooK1E3A8HZ2cICw//z5y8bGRpFb4eEKbDECs9rJU6f/wFIY8en17r27zk5QN927f9/N1RnKvnc/LTkJwtbR0lyxanVMZATQY5u2bK0sKyHWrUeOHW/v6n73/r2rlw+aupIC7GGJB4DDFZou796/j2Dfu5eVl7980UJGRsaK0pKahqb5CxdZWVoA2fgNRHGrjZXl1g3rSHUTLrB3xzY4ex8SG1lcUUFh6QJiq8NB2nbBCoaSWwF4tT3fhH8/NgAAAABJRU5ErkJggg==" name="Objet16" align="absmiddle" hspace="8" width="57" height="22"&gt;&lt;/p&gt;
			&lt;/td&gt;
			&lt;td width="11%" style="border: none; padding: 0mm"&gt;
				&lt;p align="right"&gt;(1)&lt;/p&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
&lt;/table&gt;
&lt;p&gt;Vous pouvez évidemment faire un renvoi vers cette équation.
Allez dans &lt;i&gt;Barre d’outil&amp;nbsp;: Insertion &amp;gt; Renvoi…&lt;/i&gt;&lt;span style="font-style: normal"&gt;
Dans &lt;/span&gt;&lt;i&gt;Type de champ&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
sélectionnez Texte. Dans &lt;/span&gt;&lt;i&gt;Sélection&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
sélectionnez le numéro de votre équation. Dans &lt;/span&gt;&lt;i&gt;Insérer
une référence à&lt;/i&gt;&lt;span style="font-style: normal"&gt;, choisissez
&lt;/span&gt;&lt;i&gt;Référence&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images7" align="left" width="545" height="481" border="0"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3183_1136772109"&gt;&lt;/a&gt;7 Bibliographie&lt;/h1&gt;
&lt;p&gt;La bibliographie se gère de deux manières différentes pour ce
qui est du stockage de l'information mais se gère de la même
manière que la table des matières pour l’affichage.&lt;/p&gt;
&lt;h2 class="western"&gt;7.1 Constitution de la bibliographie&lt;/h2&gt;
&lt;p&gt;Vous avez deux manières de stocker vos informations
bibliographiques&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;Soit dans une base de données LibreOffice, pour cela
	utilisez LibreOffice Base, ainsi vos données seront réutilisables
	dans tous les documents LibreOffice manipulés sur votre ordinateur.
	À vérifier, la possibilité de réaliser une base de données
	LibreOffice accessible par le réseau et donc utilisable à
	plusieurs en simultanément.&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Soit dans le document sur lequel vous êtes en train de
	travailler, pour que quelqu’un d’autre puisse le manipuler sans
	devoir accéder à la base de données, impossible de réutiliser
	les données dans un autre document.&lt;/p&gt;
&lt;/ul&gt;
&lt;p&gt;Nous allons voir la deuxième possibilité. Pour créer une entrée
de bibliographie&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;Cliquez sur &lt;i&gt;Insertion &amp;gt; Index et Tables &amp;gt; Entrées
	de bibliographie&lt;/i&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Choisissez &lt;i&gt;à partir du contenu du document &lt;/i&gt;(l’autre
	option si vous utilisez une base de données)&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Cliquez sur &lt;i&gt;Nouveau&lt;/i&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Choisissez un type et remplissez les données, puis cliquez
	sur &lt;i&gt;OK&lt;/i&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Votre entrée de bibliographie est prête à être insérée
	n’importe où dans le document, autant de fois que souhaité en
	cliquant sur &lt;i&gt;Insérer&lt;/i&gt;.&lt;/p&gt;
&lt;/ul&gt;
&lt;h2 class="western"&gt;7.2 Affichage de la bibliographie&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;Cliquez sur &lt;i&gt;Insertion &amp;gt; Index et Tables &amp;gt; Index et
	tables&lt;/i&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Dans type, choisir &lt;i&gt;Bibliographie&lt;/i&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Comme pour la table des matières, vous avez accès à tout
	un tas d'options (que vous pourrez modifier par la suite),&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Cliquez sur &lt;i&gt;OK &lt;/i&gt;pour finir.&lt;/p&gt;
&lt;/ul&gt;
&lt;p&gt;Votre bibliographie est prête. Elle se mettra à jour en allant
sur &lt;i&gt;Outils &amp;gt; Actualiser &amp;gt; l'option que vous souhaitez&lt;/i&gt;.&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__310_726403024"&gt;&lt;/a&gt;8 Notes
de bas de page&lt;/h1&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__312_726403024"&gt;&lt;/a&gt;9 Format
de page&lt;/h1&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3162_1880578451"&gt;&lt;/a&gt;10 Les
diagrammes et objets OLE&lt;/h1&gt;
&lt;h2 class="western"&gt;10.1 Diagrammes&lt;/h2&gt;
&lt;p&gt;Vous pouvez insérer des diagrammes (histogramme, nuage de points)
dans vos documents LibreOffice sans utiliser des images. Allez dans
&lt;i&gt;Barre d’outils&amp;nbsp;: Insertions &amp;gt; Objet &amp;gt; Diagramme…&lt;/i&gt;
&lt;/p&gt;
&lt;h2 class="western"&gt;10.2 Autres objets OLE&lt;/h2&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__314_726403024"&gt;&lt;/a&gt;11 Illustrations&lt;/h1&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__3166_1880578451"&gt;&lt;/a&gt;11.1 Créer
une illustration&lt;/h2&gt;
&lt;p&gt;Vous savez insérer des images dans votre fichier. C’est bien.
Mais vous voulez peut-être mettre une légende à cette image, ou
faire une table à la fin de votre rapport rappelant toutes les
images insérées dans votre document.&lt;/p&gt;
&lt;p&gt;C’est très simple&amp;nbsp;: faîtes un clic droit sur votre image
et choisissez &lt;i&gt;L&lt;/i&gt;&lt;i&gt;égende&lt;/i&gt;&lt;i&gt;… &lt;/i&gt;&lt;span style="font-style: normal"&gt;Dans
la boîte légende, tapez votre légende. &lt;/span&gt;&lt;span style="font-style: normal"&gt;Par
défaut, votre légende sera précédée de &lt;/span&gt;&lt;i&gt;Illustration&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
Dans le champ &lt;/span&gt;&lt;i&gt;Catégorie&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
vous pouvez choisir &lt;/span&gt;&lt;i&gt;&amp;lt;Aucun(e)&amp;gt;&lt;/i&gt;&lt;span style="font-style: normal"&gt;
pour supprimer ce mot. Par contre, dans ce cas vous ne pourrez faire
apparaître votre illustration dans la table. Vous pouvez en revanche
choisir votre propre nom&amp;nbsp;: sélectionnez le texte dans &lt;/span&gt;&lt;i&gt;Catégorie&lt;/i&gt;&lt;span style="font-style: normal"&gt;
et entrez votre texte.&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;Vous pouvez choisir votre numérotation,
séparateur…&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__3168_1880578451"&gt;&lt;/a&gt;11.2 Table
des illustrations&lt;/h2&gt;
&lt;p style="font-style: normal"&gt;Pour créer une table des
illustrations, il faut procéder de façon analogue à la création
de table des matières. Allez dans le menu &lt;i&gt;Insertion &amp;gt; Index et
tables &amp;gt; Index et tables… &lt;/i&gt;Dans le type d’index, choisissez
&lt;i&gt;Index des illustrations&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a name="__RefHeading__316_726403024"&gt;&lt;/a&gt;&lt;img src="data:image/png;base64,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" name="images1" align="left" width="643" height="350" border="0"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__1293_1283162286"&gt;&lt;/a&gt;12 Métadonnées&lt;/h1&gt;
&lt;p&gt;Vous pouvez ajouter des informations supplémentaires à votre
document, tel que auteur, la licence, des mots clés… Lors de
l’export en pdf par exemple, ces informations seront disponibles
via la fenêtre de propriété du document.&lt;/p&gt;
&lt;p&gt;Pour ajouter les métadonnées, allez dans &lt;i&gt;Barre d’outils&amp;nbsp;:
Fichier &amp;gt; Propriétés…&lt;/i&gt;&lt;span style="font-style: normal"&gt;
Vous n’avez plus qu’à remplir les champs. Les données
d’identités (principalement utiles dans un contexte professionnel)
se trouve dans le menu &lt;/span&gt;&lt;i&gt;Outils &amp;gt; Options…&lt;/i&gt;&lt;span style="font-style: normal"&gt;,
puis dans la section &lt;/span&gt;&lt;i&gt;LibreOffice &amp;gt; Données d’identités&lt;/i&gt;&lt;span style="font-style: normal"&gt;.
Vous n’avez plus qu’à compléter avec votre nom, votre adresse…&lt;/span&gt;&lt;/p&gt;
&lt;p style="font-style: normal"&gt;&lt;img src="data:image/png;base64,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" name="images4" align="left" width="643" height="386" border="0"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__1875_1907339193"&gt;&lt;/a&gt;13 Formulaires&lt;/h1&gt;
&lt;p&gt;Vous pouvez générer des formulaires avec LibreOffice, ce qui
vous permettra d’envoyer des documents par exemple au format PDF,
et de les recevoir remplis. Plus besoin que les personnes les
impriment pour les remplir et les scanner pour renvoi.&lt;/p&gt;
&lt;p&gt;Pour cela, aller dans &lt;i&gt;Affichage &amp;gt; Barres d’outils &amp;gt;
Contrôles de formulaire&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;Cliquer sur «&amp;nbsp;&lt;i&gt;activer le mode Ébauche&lt;/i&gt;&amp;nbsp;», les
boutons permettant de placer des éléments de formulaire vont
devenir disponibles.&lt;/p&gt;
&lt;p&gt;Il faudra aller dans les options de chaque élément pour
configurer les valeurs possibles pour une liste de sélection,
l’étiquette de l’élément, etc.&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__1877_1907339193"&gt;&lt;/a&gt;14 Publipostage&lt;/h1&gt;
&lt;p&gt;Le publipostage sert à générer des documents personnalisés à
partir d’une base de données. Par exemple, générer des badges à
partir de nom et prénom dans la base de données.&lt;/p&gt;
&lt;p&gt;Le principe est de connecter le document à une base de données
LibreOffice (qui peut être une base de données MySQL, LibreOffice,
un fichier CSV, etc.) afin de placer dans le document des balises
représentant les colonnes de cette base de données, puis de faire
l’export durant lequel LibreOffice va remplacer les balises par les
valeurs de la base de données.&lt;/p&gt;
&lt;p&gt;Pour ce faire&amp;nbsp;:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;p&gt;&lt;i&gt;Édition &amp;gt; Changer de base de données...&lt;/i&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Sélectionner la base de données qui vous intéresse.&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;LibreOffice va afficher les colonnes détectées.&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Il suffit de faire un glisser-déposer des entêtes des
	colonnes pour positionner les balises dans le document.&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Une fois la mise en page faite, &lt;i&gt;Outils &amp;gt; Assistant
	Mailing..&lt;/i&gt;.&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Suivre les étapes.&lt;/p&gt;
&lt;/ol&gt;
&lt;p&gt;Note&amp;nbsp;: je conseille de faire une copie du document
LibreOffice au cas où le document modèle ne soit écrasé par celui
contenant le publipostage.&lt;/p&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3661_1880578451"&gt;&lt;/a&gt;15 Références&lt;/h1&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__318_726403024"&gt;&lt;/a&gt;16 Suivis
des modifications&lt;/h1&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__320_726403024"&gt;&lt;/a&gt;17 Les
bonus&lt;/h1&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__322_726403024"&gt;&lt;/a&gt;17.1 Faire
des dessins&lt;/h2&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__2673_1283162286"&gt;&lt;/a&gt;17.2 Exporter
son document&lt;/h2&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__324_726403024"&gt;&lt;/a&gt;17.3 Les
PDF hybrides&lt;/h2&gt;
&lt;p&gt;Vous avez peut-être déjà été confronté au cas suivant&amp;nbsp;:
vous voulez envoyer un document par e-mail et qu’il reste
modifiable mais vous ne savez pas si votre correspondant dispose de
LibreOffice. Eh bien, vous pouvez au moins lui permettre de le lire.
Pour cela, nous allons créer des PDF hybrides.&lt;/p&gt;
&lt;p&gt;Qu’est-ce qu’un PDF hybride&amp;nbsp;? C’est en apparence un PDF
normal qui s’ouvre comme n’importe quel autre PDF. Mais il
contient également une copie de votre document texte. Si vous ouvrez
un tel PDF avec Writer, vous croirez éditer un odt.&lt;/p&gt;
&lt;p&gt;Pour créer un tel PDF, aller dans &lt;i&gt;Barre d’outil&amp;nbsp;:
Fichier &amp;gt; Exporter au format PDF…&lt;/i&gt; Dans la fenêtre qui
s’ouvre sélectionnez &lt;i&gt;Incorporer le fichier OpenDocument&lt;/i&gt;&lt;span style="font-style: normal"&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="data:image/png;base64,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" name="images3" align="left" width="643" height="366" border="0"&gt;&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__326_726403024"&gt;&lt;/a&gt;17.4 LaTeX
et LibreOffice&lt;/h2&gt;
&lt;h3 class="western"&gt;&lt;a name="__RefHeading__328_726403024"&gt;&lt;/a&gt;17.4.1 L’import&lt;/h3&gt;
&lt;h3 class="western"&gt;&lt;a name="__RefHeading__330_726403024"&gt;&lt;/a&gt;17.4.2 L’export&lt;/h3&gt;
&lt;h2 class="western"&gt;&lt;a name="__RefHeading__332_726403024"&gt;&lt;/a&gt;17.5 Envoyer
des documents sur les serveurs de l’école facilement&lt;/h2&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__334_726403024"&gt;&lt;/a&gt;18 Auteurs
et licence&lt;/h1&gt;
&lt;p&gt;Ce tutoriel a été écrit par Julien Enselme (&lt;a href="mailto:jenselme@ec-m.fr"&gt;jenselme@ec-m.fr&lt;/a&gt;).
Il est publié sous licence CC-BY-SA. Vous pouvez trouver une version
actualisée de ce document&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;en ligne:
	&lt;a href="http://www.jujens.eu/posts/2013/Oct/25/tuto_LibreOffice_Writer_avance/"&gt;http://www.jujens.eu/posts/2013/Oct/25/tuto_LibreOffice_Writer_avance/&lt;/a&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;en pdf&amp;nbsp;:
	&lt;a href="http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_avance.pdf"&gt;http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_avance.pdf&lt;/a&gt;&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;en odt&amp;nbsp;:
	&lt;a href="http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_avance.odt"&gt;http://www.jujens.eu/static/libreoffice/tuto_LibreOffice_Writer_avance.odt&lt;/a&gt;&lt;/p&gt;
&lt;/ul&gt;
&lt;p&gt;Liste des contributeurs&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;&lt;a href="http://assos.centrale-marseille.fr/ftorregrosa"&gt;Florent Torregrosa&lt;/a&gt; (bibliographie, formulaire, publipostage).&lt;/p&gt;
&lt;/ul&gt;
&lt;h1 class="western"&gt;&lt;a name="__RefHeading__3185_1136772109"&gt;&lt;/a&gt;19 Pour
aller plus loin&lt;/h1&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;p&gt;La documentation officielle de LibreOffice&amp;nbsp;:
	&lt;a href="https://www.libreoffice.org/get-help/documentation/"&gt;https://www.libreoffice.org/get-help/documentation/&lt;/a&gt;
		&lt;/p&gt;
	&lt;li&gt;&lt;p&gt;Le publipostage&amp;nbsp;:
	&lt;a href="http://ia71.ac-dijon.fr/chalon2/tutoriels/oo/Publipostage_OOo.pdf"&gt;http://ia71.ac-dijon.fr/chalon2/tutoriels/oo/Publipostage_OOo.pdf&lt;/a&gt;&lt;/p&gt;
&lt;/ul&gt;
</content><category term="Libreoffice"></category><category term="LibreOffice Writer tutoriel"></category></entry><entry><title>LaTeX : annexe</title><link href="//www.jujens.eu/posts/2013/Oct/20/latex-annexe/" rel="alternate"></link><published>2013-10-20T00:00:00+02:00</published><updated>2013-10-20T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-20:/posts/2013/Oct/20/latex-annexe/</id><summary type="html">&lt;p&gt;Comment faire des annexes (numéroté par des lettres plutôt que par des chiffres) en LaTeX ? C’est très facile avec le paquet appendix. Il suffit juste de l’utiliser : &lt;tt class="docutils literal"&gt;\usepackage{appendix}&lt;/tt&gt;. Ensuite, placé toutes vos annexes dans l’environnement appendix comme ci-dessous.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;appendix&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Les micromodules&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\label&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;a&lt;span class="nb"&gt;_ …&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;Comment faire des annexes (numéroté par des lettres plutôt que par des chiffres) en LaTeX ? C’est très facile avec le paquet appendix. Il suffit juste de l’utiliser : &lt;tt class="docutils literal"&gt;\usepackage{appendix}&lt;/tt&gt;. Ensuite, placé toutes vos annexes dans l’environnement appendix comme ci-dessous.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;appendix&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Les micromodules&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\label&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;a&lt;span class="nb"&gt;_&lt;/span&gt;micro&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.4, angle=90]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;./img/micro.jpg&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;L’encartage bancaire&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\label&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;a&lt;span class="nb"&gt;_&lt;/span&gt;encartage&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.28, angle=90]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;./img/encartage.jpg&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;La personnalisation&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\label&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;a&lt;span class="nb"&gt;_&lt;/span&gt;perso&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.28, angle=90]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;./img/perso.jpg&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Les différentes étapes de la production&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\label&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;a&lt;span class="nb"&gt;_&lt;/span&gt;prod&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.5, angle=0]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;./img/stage&lt;span class="nb"&gt;_&lt;/span&gt;prod.png&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;appendix&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="LaTeX"></category></entry><entry><title>LaTeX : glossaire</title><link href="//www.jujens.eu/posts/2013/Oct/20/latex-glossaire/" rel="alternate"></link><published>2013-10-20T00:00:00+02:00</published><updated>2013-10-20T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-20:/posts/2013/Oct/20/latex-glossaire/</id><summary type="html">&lt;p&gt;Pour mon rapport de stage, j’ai eu besoin de faire un glossaire en LaTeX. Contrairement à ce que l’on pourrait croire, c’est assez simple grâce au paquet glossaries. L’option nonumberlist permet de ne pas avoir les numéros de pages pour lesquelles le terme est utilisé à …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Pour mon rapport de stage, j’ai eu besoin de faire un glossaire en LaTeX. Contrairement à ce que l’on pourrait croire, c’est assez simple grâce au paquet glossaries. L’option nonumberlist permet de ne pas avoir les numéros de pages pour lesquelles le terme est utilisé à côté du texte explicatif.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="na"&gt;[12pt]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;report&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[frenchb]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;libertine&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[nonumberlist]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;glossaries&lt;span class="nb"&gt;}&lt;/span&gt;Cela fait un moment que je me demande comment changer l’apparence des titres de chapitre sous LaTeX. Parce que avoir un gros Chapitre 1 ce n’est pas toujours ce que je veux.
&lt;/pre&gt;&lt;/div&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;Heureusement, le paquet titlesec vient à la rescousse. Il ajoute la commande titleformat Ainsi, pour avoir un titre qui ressemble à ça :&lt;/dt&gt;
&lt;dd&gt;&lt;p class="first"&gt;makeglossaries&lt;/p&gt;
&lt;p class="last"&gt;begin{document}
input{includes/glossaire.tex}
end{document}&lt;/p&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Et dans le fichier glossaire.tex :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\newglossaryentry&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;waffer&lt;span class="nb"&gt;}{&lt;/span&gt;name=&lt;span class="nb"&gt;{&lt;/span&gt;waffer&lt;span class="nb"&gt;}&lt;/span&gt;, description=&lt;span class="nb"&gt;{&lt;/span&gt;Un waffer est la plaque sur laquelle se trouve les puces. C’est sous cette forme que Gemalto reçoit les puces de son fournisseur&lt;span class="nb"&gt;}}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="LaTeX"></category></entry><entry><title>LaTeX : une jolie page de garde</title><link href="//www.jujens.eu/posts/2013/Oct/20/latex-page-garde/" rel="alternate"></link><published>2013-10-20T00:00:00+02:00</published><updated>2013-10-20T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-20:/posts/2013/Oct/20/latex-page-garde/</id><summary type="html">&lt;p&gt;LaTeX sait faire des pages de titre avec la commande maketitle si on a au préalable renseigné les champs &lt;tt class="docutils literal"&gt;\author{Moi}&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\date{\today}&lt;/span&gt;&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;\title{Mon titre}&lt;/tt&gt;. Néanmoins, elle fait un peu austère. Heureusement, l’environement titlepage vient à la rescousse. Avec le code ci-dessous, on obtient un très beau …&lt;/p&gt;</summary><content type="html">&lt;p&gt;LaTeX sait faire des pages de titre avec la commande maketitle si on a au préalable renseigné les champs &lt;tt class="docutils literal"&gt;\author{Moi}&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\date{\today}&lt;/span&gt;&lt;/tt&gt; et &lt;tt class="docutils literal"&gt;\title{Mon titre}&lt;/tt&gt;. Néanmoins, elle fait un peu austère. Heureusement, l’environement titlepage vient à la rescousse. Avec le code ci-dessous, on obtient un très beau résultat.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="na"&gt;[12pt, openany]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;report&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[a4paper,left=2cm,right=2cm,top=2cm,bottom=2cm]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;geometry&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[frenchb]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;libertine&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[pdftex]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;graphicx&lt;span class="nb"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\setlength&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\parindent&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;0cm&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\setlength&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\parskip&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;1ex plus 0.5ex minus 0.2ex&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newcommand&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\hsp&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\hspace&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;20pt&lt;span class="nb"&gt;}}&lt;/span&gt;
&lt;span class="k"&gt;\newcommand&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\HRule&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\rule&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\linewidth&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;0.5mm&lt;span class="nb"&gt;}}&lt;/span&gt;

&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;titlepage&lt;span class="nb"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;sffamily&lt;span class="nb"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;% Upper part of the page. The &amp;#39;~&amp;#39; is needed because \\&lt;/span&gt;
    &lt;span class="c"&gt;% only works if a paragraph has started.&lt;/span&gt;
    &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.04]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;img1.JPG&lt;span class="nb"&gt;}&lt;/span&gt;~&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[1.5cm]&lt;/span&gt;

    &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\LARGE&lt;/span&gt; École Centrale Marseille&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[2cm]&lt;/span&gt;

    &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\Large&lt;/span&gt; Rapport de stage 1A&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[1.5cm]&lt;/span&gt;

    &lt;span class="c"&gt;% Title&lt;/span&gt;
    &lt;span class="k"&gt;\HRule&lt;/span&gt; &lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[0.4cm]&lt;/span&gt;
    &lt;span class="nb"&gt;{&lt;/span&gt; &lt;span class="k"&gt;\huge&lt;/span&gt; &lt;span class="k"&gt;\bfseries&lt;/span&gt; Opérateur expédition produits finis&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[0.4cm]&lt;/span&gt; &lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\HRule&lt;/span&gt; &lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[2cm]&lt;/span&gt;
    &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.2]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;img2.JPG&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[2cm]&lt;/span&gt;

    &lt;span class="c"&gt;% Author and supervisor&lt;/span&gt;
    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}{&lt;/span&gt;0.4&lt;span class="k"&gt;\textwidth&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushleft&lt;span class="nb"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\large&lt;/span&gt;
        Moi &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Même&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;
        Promo 2015&lt;span class="k"&gt;\\&lt;/span&gt;
      &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushleft&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}{&lt;/span&gt;0.4&lt;span class="k"&gt;\textwidth&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushright&lt;span class="nb"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\large&lt;/span&gt;
        &lt;span class="k"&gt;\emph&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Tuteur :&lt;span class="nb"&gt;}&lt;/span&gt; M. Le &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Tuteur&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;
        &lt;span class="k"&gt;\emph&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Chef d&amp;#39;équipe : &lt;span class="nb"&gt;}&lt;/span&gt; M. Chef &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;D’Équipe&lt;span class="nb"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushright&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\vfill&lt;/span&gt;

    &lt;span class="c"&gt;% Bottom of the page&lt;/span&gt;
    &lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\large&lt;/span&gt; 1&lt;span class="k"&gt;\ier&lt;/span&gt;&lt;span class="nb"&gt;{}&lt;/span&gt; Juillet 2013 — 30 Août 2013&lt;span class="nb"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;sffamily&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;titlepage&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;img alt="La page de garde" src="/images/LaTeX_pageTitle.png" /&gt;
</content><category term="Trucs et astuces"></category><category term="LaTeX"></category></entry><entry><title>LaTeX : de jolis titres</title><link href="//www.jujens.eu/posts/2013/Oct/20/latex-titres/" rel="alternate"></link><published>2013-10-20T00:00:00+02:00</published><updated>2013-10-20T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-20:/posts/2013/Oct/20/latex-titres/</id><summary type="html">&lt;p&gt;Cela fait un moment que je me demande comment changer l’apparence des titres de chapitre sous LaTeX. Parce que avoir un gros Chapitre 1 ce n’est pas toujours ce que je veux.&lt;/p&gt;
&lt;p&gt;Heureusement, le paquet titlesec vient à la rescousse. Il ajoute la commande titleformat Ainsi, pour avoir …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Cela fait un moment que je me demande comment changer l’apparence des titres de chapitre sous LaTeX. Parce que avoir un gros Chapitre 1 ce n’est pas toujours ce que je veux.&lt;/p&gt;
&lt;p&gt;Heureusement, le paquet titlesec vient à la rescousse. Il ajoute la commande titleformat Ainsi, pour avoir un titre qui ressemble à ça :&lt;/p&gt;
&lt;img alt="Rendu du titre" src="/images/LaTeX_titlesec.png" /&gt;
&lt;p&gt;Utilisez simplement :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="na"&gt;[12pt, openany]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;report&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[frenchb]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;libertine&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;titlesec&lt;span class="nb"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\newcommand&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\hsp&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\hspace&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;20pt&lt;span class="nb"&gt;}}&lt;/span&gt;

&lt;span class="k"&gt;\titleformat&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;[hang]&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\Huge\bfseries\sffamily&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\thechapter\hsp&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;0pt&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\Huge\bfseries\sffamily&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\chapter&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Introduction&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cela enlève à la fois le chapter et modifie la police pour avoir celle qui me convient.&lt;/p&gt;
&lt;p&gt;Citons également le paquet fncychap et le type de document memoire (documentclass{memoir}) qui changent également l’apparence des titres.&lt;/p&gt;
&lt;div class="section" id="source"&gt;
&lt;h2&gt;Source&lt;/h2&gt;
&lt;p&gt;Pour voir encore plus de titre : &lt;a class="reference external" href="http://texblog.org/2012/07/03/fancy-latex-chapter-styles/"&gt;http://texblog.org/2012/07/03/fancy-latex-chapter-styles/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="LaTeX"></category></entry><entry><title>LaTeX: a nice front page</title><link href="//www.jujens.eu/posts/en/2013/Oct/20/latex-page-garde/" rel="alternate"></link><published>2013-10-20T00:00:00+02:00</published><updated>2013-10-20T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-10-20:/posts/en/2013/Oct/20/latex-page-garde/</id><summary type="html">&lt;p&gt;LaTeX can make front pages with the &lt;tt class="docutils literal"&gt;\maketitle&lt;/tt&gt; command if the fields
&lt;tt class="docutils literal"&gt;\author{Me}&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\date{\today}&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;\title{My title}&lt;/tt&gt; are
filled. However, it is quite dry. Luckily, the &lt;tt class="docutils literal"&gt;titlepage&lt;/tt&gt; environment comes
to the rescue: with the code below, you can get a very nice result!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="na"&gt;[12pt, openany]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;report …&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;LaTeX can make front pages with the &lt;tt class="docutils literal"&gt;\maketitle&lt;/tt&gt; command if the fields
&lt;tt class="docutils literal"&gt;\author{Me}&lt;/tt&gt;, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;\date{\today}&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;\title{My title}&lt;/tt&gt; are
filled. However, it is quite dry. Luckily, the &lt;tt class="docutils literal"&gt;titlepage&lt;/tt&gt; environment comes
to the rescue: with the code below, you can get a very nice result!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;\documentclass&lt;/span&gt;&lt;span class="na"&gt;[12pt, openany]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;report&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[utf8]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;inputenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[T1]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;fontenc&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[a4paper,left=2cm,right=2cm,top=2cm,bottom=2cm]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;geometry&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[frenchb]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;babel&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;libertine&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\usepackage&lt;/span&gt;&lt;span class="na"&gt;[pdftex]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;graphicx&lt;span class="nb"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\setlength&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\parindent&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;0cm&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\setlength&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\parskip&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;1ex plus 0.5ex minus 0.2ex&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\newcommand&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\hsp&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\hspace&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;20pt&lt;span class="nb"&gt;}}&lt;/span&gt;
&lt;span class="k"&gt;\newcommand&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\HRule&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;&lt;span class="k"&gt;\rule&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\linewidth&lt;/span&gt;&lt;span class="nb"&gt;}{&lt;/span&gt;0.5mm&lt;span class="nb"&gt;}}&lt;/span&gt;

&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;titlepage&lt;span class="nb"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;sffamily&lt;span class="nb"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;% Upper part of the page. The &amp;#39;~&amp;#39; is needed because \\&lt;/span&gt;
    &lt;span class="c"&gt;% only works if a paragraph has started.&lt;/span&gt;
    &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.04]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;img1.JPG&lt;span class="nb"&gt;}&lt;/span&gt;~&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[1.5cm]&lt;/span&gt;

    &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\LARGE&lt;/span&gt; École Centrale Marseille&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[2cm]&lt;/span&gt;

    &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\Large&lt;/span&gt; Rapport de stage 1A&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[1.5cm]&lt;/span&gt;

    &lt;span class="c"&gt;% Title&lt;/span&gt;
    &lt;span class="k"&gt;\HRule&lt;/span&gt; &lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[0.4cm]&lt;/span&gt;
    &lt;span class="nb"&gt;{&lt;/span&gt; &lt;span class="k"&gt;\huge&lt;/span&gt; &lt;span class="k"&gt;\bfseries&lt;/span&gt; Opérateur expédition produits finis&lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[0.4cm]&lt;/span&gt; &lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\HRule&lt;/span&gt; &lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[2cm]&lt;/span&gt;
    &lt;span class="k"&gt;\includegraphics&lt;/span&gt;&lt;span class="na"&gt;[scale=0.2]&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;img2.JPG&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\\&lt;/span&gt;&lt;span class="na"&gt;[2cm]&lt;/span&gt;

    &lt;span class="c"&gt;% Author and supervisor&lt;/span&gt;
    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}{&lt;/span&gt;0.4&lt;span class="k"&gt;\textwidth&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushleft&lt;span class="nb"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\large&lt;/span&gt;
        Moi &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Même&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;
        Promo 2015&lt;span class="k"&gt;\\&lt;/span&gt;
      &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushleft&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}{&lt;/span&gt;0.4&lt;span class="k"&gt;\textwidth&lt;/span&gt;&lt;span class="nb"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;\begin&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushright&lt;span class="nb"&gt;}&lt;/span&gt; &lt;span class="k"&gt;\large&lt;/span&gt;
        &lt;span class="k"&gt;\emph&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Tuteur :&lt;span class="nb"&gt;}&lt;/span&gt; M. Le &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Tuteur&lt;span class="nb"&gt;}&lt;/span&gt;&lt;span class="k"&gt;\\&lt;/span&gt;
        &lt;span class="k"&gt;\emph&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;Chef d&amp;#39;équipe : &lt;span class="nb"&gt;}&lt;/span&gt; M. Chef &lt;span class="k"&gt;\textsc&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;D’Équipe&lt;span class="nb"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;flushright&lt;span class="nb"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;minipage&lt;span class="nb"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;\vfill&lt;/span&gt;

    &lt;span class="c"&gt;% Bottom of the page&lt;/span&gt;
    &lt;span class="nb"&gt;{&lt;/span&gt;&lt;span class="k"&gt;\large&lt;/span&gt; 1&lt;span class="k"&gt;\ier&lt;/span&gt;&lt;span class="nb"&gt;{}&lt;/span&gt; Juillet 2013 — 30 Août 2013&lt;span class="nb"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;center&lt;span class="nb"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;sffamily&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;titlepage&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;\end&lt;/span&gt;&lt;span class="nb"&gt;{&lt;/span&gt;document&lt;span class="nb"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;img alt="The title page" src="/images/LaTeX_pageTitle.png" /&gt;
</content><category term="Trucs et astuces"></category><category term="LaTeX"></category></entry><entry><title>Pourquoi j'abandonne LaTeX et je passe à org-mode</title><link href="//www.jujens.eu/posts/2013/Aug/23/de-latex-a-orgmode/" rel="alternate"></link><published>2013-08-23T00:00:00+02:00</published><updated>2013-08-23T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-08-23:/posts/2013/Aug/23/de-latex-a-orgmode/</id><summary type="html">&lt;p class="first last"&gt;Oui, LaTeX est surpuissant et permet de faire de très belles choses étrange assez facilement. Même si je lui préfère LibreOffice pour certaines tâches (tout ce qui contient beaucoup d'images notamment), j'aime LaTeX (et j'ai même fait mon CV en LaTeX ;-)). LaTeX nous force à organiser le contenu, tout est un dans fichier texte (ce qui est à mon avis pérenne) et pouvoir tout faire au clavier est un gros plus (on ne se perd pas dans l'interface). Pour contre, soyons franc parfois ce n'est pas évident d'avoir le résultat souhaité et il faut chercher sur pleins de forum et mettre les mains dans le camboui.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Oui, LaTeX est surpuissant et permet de faire de très belles choses
étrange assez facilement. Même si je lui préfère LibreOffice pour
certaines tâches (tout ce qui contient beaucoup d'images notamment),
j'aime LaTeX (et j'ai même fait mon CV en LaTeX ;-)). LaTeX nous force à
organiser le contenu, tout est un dans fichier texte (ce qui est à mon
avis pérenne) et pouvoir tout faire au clavier est un gros plus (on ne
se perd pas dans l'interface).&lt;/p&gt;
&lt;p&gt;Pour contre, soyons franc parfois ce n'est pas évident d'avoir le
résultat souhaité et il faut chercher sur pleins de forum et mettre les
mains dans le camboui.&lt;/p&gt;
&lt;p&gt;Il y a quelques temps déjà, je cherchais un logiciel pour prendre des
notes. Je suis tombé sur pas mal de logiciels graphiques avant de
découvrir org-mode. C'est un mode d'Emacs intégralement dédié à la prise
de note et il est présent de façon standard depuis les dernières
versions d'Emacs. Et en plus de pouvoir remplacer LaTeX (on peut faire
de l'export vers LaTeX, html, pdf) ce logiciel fait bien plus. Et c'est
pourquoi j'abonne LaTeX pour passer à org-mode. Voyons tout de suite
pourquoi.&lt;/p&gt;
&lt;div class="section" id="la-syntaxe"&gt;
&lt;h2&gt;La syntaxe&lt;/h2&gt;
&lt;p&gt;LaTeX a une syntaxe très verbeuse, tellement verbeuse qu'elle en devient
lourde (un peu comme le HTML à mon avis) et qui utilise lourdement le
backslash pas toujours accessible facilement. À mon avis, pour l'édition
de fichier texte, la syntaxe des divers wiki est vraiment plus
performante.&lt;/p&gt;
&lt;p&gt;Et voici Org-mode. La syntaxe d'org-mode est simple et élégante. En
LaTeX pour créer un titre, il faut &lt;tt class="docutils literal"&gt;\title{Mon titre}&lt;/tt&gt; soit 8
caractères qui n'ont pas d'utilité pour le lecteur. Et pour les
sous-titres le nombre de caractères explose. En Org-mode :
&lt;tt class="docutils literal"&gt;* Mon titre&lt;/tt&gt;. Et c'est tout ! Pour faire un sous-titre
&lt;tt class="docutils literal"&gt;** Sous titre&lt;/tt&gt;. Et on peut en mettre autant que l'on veut ! Bon
seulement 6 si on veut faire de l’export html.&lt;/p&gt;
&lt;p&gt;Autre point très intéressant, Emacs va plier le texte de ces section
tout seul. Et on peut déplier facilement, en appuyant sur TAB.&lt;/p&gt;
&lt;p&gt;Pour mettre en gras, il suffit de mettre le texte entre * et pour
l'italique, entre /. Pour faire des listes, il suffit de commencer la
ligne par un - ou un nombre.&lt;/p&gt;
&lt;p&gt;Pas mal hein ? Mais on peut faire bien plus.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="les-todo-listes"&gt;
&lt;h2&gt;Les TODO listes&lt;/h2&gt;
&lt;p&gt;Comme je l'ai dis en introduction Org-mode est fait pour prendre des
notes. Mais il fait aussi des TODO list. Placez-vous sur une ligne et
tapez TODO devant celle -ci (ou utilisez le racourcis clavier
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;^-c&lt;/span&gt; &lt;span class="pre"&gt;^-e&lt;/span&gt;&lt;/tt&gt;). Lors que l'item est fait, réutiliser le raccourcis
clavier. Et hop, TODO devient DONE. Mais ce n'est pas tout. Considérons
la liste ci-dessous, que l'on écrit telle quelle dans Emacs :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
* TODO remplir mon blog [0%]
** TODO Faire des articles
- [ ] Sur Org-mode
- [ ] Sur autre chose
** TODO Finir les tutos
&lt;/pre&gt;
&lt;p&gt;Et bien Lorsqu'on aura coché toutes les cases de Faire des articles
(avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;^-c&lt;/span&gt; &lt;span class="pre"&gt;^-e&lt;/span&gt;&lt;/tt&gt;), cette item passera en DONE automatiquement et le
pourcentage de complétion de Remplir mon blog passera à 50% (si ce
pourcentage est faux, forcer sa réévaluation avec &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;^-c&lt;/span&gt; &lt;span class="pre"&gt;^-c&lt;/span&gt;&lt;/tt&gt;).&lt;/p&gt;
&lt;pre class="literal-block"&gt;
* TODO remplir mon blog [50%]
** DONE Faire des articles
- [X] Sur Org-mode
- [X] Sur autre chose
** TODO Finir les tutos
&lt;/pre&gt;
&lt;p&gt;Plutôt pas mal, non ?&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="ils-sont-beaux-mes-tableaux-ils-sont-beaux"&gt;
&lt;h2&gt;Ils sont beaux mes tableaux, ils sont beaux&lt;/h2&gt;
&lt;p&gt;Autre point très lourd en LaTeX : les tableaux. La syntaxe est lourde et
on ne sait pas forcément quel sera le résultat. En Org-mode c'est simple
et efficace (vous vous en seriez doutez). Entrez :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
| Produits | Prix |
|-
&lt;/pre&gt;
&lt;p&gt;Appuyez sur TAB et hop :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
| Produits | Prix |
|----------+------|
|          |      |
&lt;/pre&gt;
&lt;p&gt;Et on continue à modifier en appuyant sur TAB pour passer d'une case à
l'autre (Emacs va les ajouter tout seul) et les redimensionner comme un
grand.&lt;/p&gt;
&lt;p&gt;Et on peut même le transformer en tableur, mais là je vous revoie vers
la
&lt;a class="reference external" href="http://orgmode.org/worg/org-tutorials/org-spreadsheet-intro.html"&gt;doc&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="l-export"&gt;
&lt;h2&gt;L'export&lt;/h2&gt;
&lt;p&gt;Mais un joli fichier texte n'est pas adapté pour tout les usages. Un
petit pdf (très joli car généré par LaTeX) ou un fichier html peut être
plus approprié. Org-mode peut évidemment exporter votre TODO liste. Il
existe plein de raccourcis clavier complexe (c'est un peu le problème
d'Emacs) mais vous pouvez aussi passer par les menus (c'est un peu l'un
des avantages d'Emacs sur vim). Ou alors :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
M-x org-mode-export-TAB
&lt;/pre&gt;
&lt;p&gt;Et choisissez l'export qui vous convient.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="on-peut-faire-du-latex-avec"&gt;
&lt;h2&gt;On peut faire du LaTeX avec&lt;/h2&gt;
&lt;p&gt;Les syntaxes légères c'est bien joli mais parfois ce n'est pas
suffisant. Si je veux faire des équations très compliquées avec pleins
de symboles étranges ça ne suffit pas. Heureusement, avec Org-mode on
peut insérer du code LaTeX directement, sans modification. Il sera
conservé lors de l'export en LaTeX et interprété lors de la compilation
en pdf (même si vous exportez directement en pdf). Je peux donc faire :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
* Equation de Jenselme
La voilà, avec $h = \frac{h}{2}$ :
$$\frac{p}{2m}|\Psi&amp;gt; + \sum_{i = 1}^{N} x^i = 0$$
&lt;/pre&gt;
&lt;p&gt;Et on obtient après compilation :&lt;/p&gt;
&lt;p&gt;&lt;img alt="image0" src="/images/equation_jenselme.png" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Voilà pourquoi je passe à Org-mode. On peut évidemment aussi faire des
présentations en beamer avec (avec une jolie syntaxe toute simple et
très claire), mettre du code source, le transformer en calendrier à
partir des TODO list en mettant une date de fin,… Je vous laisse
regarder la doc pour ça.&lt;/p&gt;
&lt;/div&gt;
</content><category term="Blog"></category><category term="Emacs"></category><category term="Org-mode"></category><category term="LaTeX"></category></entry><entry><title>Emacs : se connecter en ssh</title><link href="//www.jujens.eu/posts/2013/Aug/08/emacs-connecter-ssh/" rel="alternate"></link><published>2013-08-08T00:00:00+02:00</published><updated>2013-08-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-08-08:/posts/2013/Aug/08/emacs-connecter-ssh/</id><summary type="html">&lt;p&gt;Emacs n’est pas installé sur le seveur où vous devez modifier des
fichiers ? Vous détestez vi et trouvez nano trop limité ? Eh bien vous
pouvez utiliser Emacs avec votre configuration habituelle !&lt;/p&gt;
&lt;p&gt;Pour que Emacs se connecte au serveur, tapez simplement : &lt;tt class="docutils literal"&gt;^x ^f /ssh2:USER&amp;#64;SEVER&lt;/tt&gt;. Emacs va alors se …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Emacs n’est pas installé sur le seveur où vous devez modifier des
fichiers ? Vous détestez vi et trouvez nano trop limité ? Eh bien vous
pouvez utiliser Emacs avec votre configuration habituelle !&lt;/p&gt;
&lt;p&gt;Pour que Emacs se connecte au serveur, tapez simplement : &lt;tt class="docutils literal"&gt;^x ^f /ssh2:USER&amp;#64;SEVER&lt;/tt&gt;. Emacs va alors se connecter en ssh au serveur et vous
pourrez naviguer dans le dossier home du serveur comme si vous étiez en
local. Vous pouvez évidememt directement préciser quel dossier/fichier
vous désirez ouvrir.&lt;/p&gt;
&lt;p&gt;C’est beau non ?&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="Emacs"></category><category term="ssh"></category><category term="Trucs et astuces"></category></entry><entry><title>Emacs : édition multiple</title><link href="//www.jujens.eu/posts/2013/Aug/08/emacs-edition-multiple/" rel="alternate"></link><published>2013-08-08T00:00:00+02:00</published><updated>2013-08-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-08-08:/posts/2013/Aug/08/emacs-edition-multiple/</id><summary type="html">&lt;p&gt;J’ai récemment eu besoin d’éditer plusieurs fichiers contenant la même
chaîne de caractères pour la remplacer. Je pensais tout d’abord utiliser
sed avant de regarder ce que pouvais faire Emacs. Eh bien non seulement
il peut le faire, mais il peut le faire facilement en vous laissant …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J’ai récemment eu besoin d’éditer plusieurs fichiers contenant la même
chaîne de caractères pour la remplacer. Je pensais tout d’abord utiliser
sed avant de regarder ce que pouvais faire Emacs. Eh bien non seulement
il peut le faire, mais il peut le faire facilement en vous laissant un
certain &amp;quot;contrôle&amp;quot; lors du remplacement.&lt;/p&gt;
&lt;div class="section" id="ouvrons-nos-fichiers"&gt;
&lt;h2&gt;Ouvrons nos fichiers&lt;/h2&gt;
&lt;p&gt;Étape 1 : trouvez tout les fichiers à éditer. Peu importe leur
localisation, on va utiliser la commande find qui s’intègre très bien
avec Emacs. Lancez Emacs. Tapez ensuite :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
M-x find-dired
&lt;/pre&gt;
&lt;p&gt;Et ouvrez le répertoire dans lequel vous voulez lancer votre recherche.
Emacs vous demande alors les options à passer à find. Allez voir le man
de find pour savoir tout ce que vous pouvez donner comme argument. Par
exemple :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
-type f -name settings.php -maxdepth 3
&lt;/pre&gt;
&lt;p&gt;ce qui nous retournera tous les fichiers nommés settings.php situé à une
profondeur maximale de 3. Libre à vous de faire plus compliqué suivant
vous besoin. (Ne vous prenez pas trop la tête non plus).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="selectionnons-les-fichiers-a-editer"&gt;
&lt;h2&gt;Sélectionnons les fichiers à éditer&lt;/h2&gt;
&lt;p&gt;Une fois la recherche terminée, Emacs vous affiche tous les résultats.
Et c’est à vous de les sélectionner. Nul besoin de trop se prendre la
tête avec find à l’étape précédente. Aller sur la ligne/le nom du
fichier à éditer et appuyez sur la touche t. Le nom du fichier change de
couleur. Il est sélectionné ! Pour sélectionner tous les fichiers, tapez m.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="cherchons-et-remplacons"&gt;
&lt;h2&gt;Cherchons et remplaçons&lt;/h2&gt;
&lt;p&gt;Tapez&lt;/p&gt;
&lt;pre class="literal-block"&gt;
M-x dired-do-query-replace-regexp
&lt;/pre&gt;
&lt;p&gt;pour procéder à la recherche. Emacs vous demande tout d’abord
l’expression régulière à chercher, puis la chaîne par laquelle il faut
la remplacer. Emacs va alors vous proposer fichier par fichier et
occurrence par occurrence le remplacement. Tapez &amp;quot;y&amp;quot; pour le faire, &amp;quot;n&amp;quot;
pour passer à l’occurrence suivante. &amp;quot;!&amp;quot; remplace toutes les occurrences
du buffer courant et &amp;quot;Y&amp;quot; toutes les occurrences dans tous les fichiers.
&amp;quot;?&amp;quot; affiche la liste complète des commandes disponibles.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="sauvegardons"&gt;
&lt;h2&gt;Sauvegardons&lt;/h2&gt;
&lt;p&gt;Pour sauvegarder tous vos fichiers en une seule fois, tapez&lt;/p&gt;
&lt;pre class="literal-block"&gt;
M-x ibuffer
&lt;/pre&gt;
&lt;p&gt;Sélectionnez les fichers non sauvegardés en tapant &lt;tt class="docutils literal"&gt;* U&lt;/tt&gt;. Sauvegarder
les avec S. Et voilà, c’est fini ;-).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Nous venons facilement de remplacer une chaîne présente dans plusieurs
fichiers. Il est évidement possible de le faire sur &lt;a class="reference external" href="//www.jujens.eu/posts/2013/Aug/08/emacs-connecter-ssh/"&gt;des fichiers
présents sur un serveur&lt;/a&gt;. Vous avez
également accès à des fonctions de sélection de fichiers plus avancées,
comme sélectionner tous les fichiers contenant une expression régulière
et à d’autres fonctions de manipulation de fichier (comme les renommer).&lt;/p&gt;
&lt;p&gt;Maintenant, vous savez quel outil prendre pour éditer vos fichiers !&lt;/p&gt;
&lt;/div&gt;
</content><category term="Trucs et astuces"></category><category term="emacs"></category></entry><entry><title>Emacs : regexp builder</title><link href="//www.jujens.eu/posts/2013/Aug/08/emacs-regexp-builder/" rel="alternate"></link><published>2013-08-08T00:00:00+02:00</published><updated>2013-08-08T00:00:00+02:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-08-08:/posts/2013/Aug/08/emacs-regexp-builder/</id><summary type="html">&lt;p&gt;Perdu avec une expression régulière ? Emacs peut vous aider ! Il propose en effet un outil intitulé regexp-builder qui vérifie la syntaxe de la regexp durant la frappe et cherche une correspondance dans le buffer courant.&lt;/p&gt;
&lt;p&gt;Pour le lancer, tapez simplement &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;M-x&lt;/span&gt; &lt;span class="pre"&gt;regexp-builder&lt;/span&gt;&lt;/tt&gt;. Entrez alors simplement votre regexp entre les guillemets …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Perdu avec une expression régulière ? Emacs peut vous aider ! Il propose en effet un outil intitulé regexp-builder qui vérifie la syntaxe de la regexp durant la frappe et cherche une correspondance dans le buffer courant.&lt;/p&gt;
&lt;p&gt;Pour le lancer, tapez simplement &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;M-x&lt;/span&gt; &lt;span class="pre"&gt;regexp-builder&lt;/span&gt;&lt;/tt&gt;. Entrez alors simplement votre regexp entre les guillemets.&lt;/p&gt;
&lt;p&gt;Attention toute fois, Emacs étant codé en Lisp, par défaut regexp-builder utilise la syntaxe de Lisp pour les regexp qui diffèrent de la syntaxe habitulle (pour ignorer un caractère, il faut utiliser &lt;tt class="docutils literal"&gt;\\&lt;/tt&gt;). Heureusement, on peut changer le mode d’édition ! Tapez &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;^-c&lt;/span&gt; TAB&lt;/tt&gt; et choisissez string pour avoir la syntaxe habituelle.&lt;/p&gt;
</content><category term="Trucs et astuces"></category><category term="Emacs"></category></entry><entry><title>Connaître le niveau d'encre de son imprimante epson</title><link href="//www.jujens.eu/posts/2013/Jan/12/niveau-encre-epson/" rel="alternate"></link><published>2013-01-12T00:00:00+01:00</published><updated>2013-01-12T00:00:00+01:00</updated><author><name>Julien Enselme</name></author><id>tag:www.jujens.eu,2013-01-12:/posts/2013/Jan/12/niveau-encre-epson/</id><content type="html">&lt;p&gt;Il suffit de lancer en root :&lt;/p&gt;
&lt;pre class="literal-block"&gt;
sudo escputil -i -r /dev/usb/lp0
&lt;/pre&gt;
</content><category term="Trucs et astuces"></category><category term="Linux"></category><category term="imprimante"></category></entry></feed>