<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>dmerej&#39;s blog</title>
    <link>https://dmerej.info/blog/</link>
    <description>Latests posts on dmerej's blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 23 Jun 2022 10:11:47 +0000</lastBuildDate>
    
        <atom:link href="https://dmerej.info/blog/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>Classes vs Types (or Yet Another Reason To Learn Rust)</title>
      <link>https://dmerej.info/blog/post/classes-vs-types/</link>
      <pubDate>Thu, 23 Jun 2022 10:11:47 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/classes-vs-types/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Note: this is both a follow-up to the &lt;a href=&#34;https://dmerej.info/blog/post/classes-suck/&#34;&gt;do classes suck&lt;/a&gt; or
&lt;a href=&#34;https://dmerej.info/blog/post/classes-rock/&#34;&gt;do classes suck&lt;/a&gt; articles, &lt;em&gt;and&lt;/em&gt;
yet another reason why you should &lt;a href=&#34;https://dmerej.info/blog/post/rust-secrets-and-logs/&#34;&gt;learn Rust&lt;/a&gt;,
so you should have read at least one of them in order to understand the context for this post.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/classes-vs-types.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;back-to-the-spec&#34;&gt;Back to the spec&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#back-to-the-spec&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;As a reminder, here&amp;rsquo;s our spec:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When robots come off the factory floor, they have no name.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The first time a robot boots, a random name is generated.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Every once in a while, the robots are reset to their factory settings, and the next time they boot, they get a &lt;em&gt;new&lt;/em&gt; random name.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;using-rust&#34;&gt;Using Rust&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-rust&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The goal of Rust is to allow to code to be 3 things at once: correct, fast, and expressive. This is no easy task and that&amp;rsquo;s why Rust is a bit complicated to learn (which is not such a bad thing in my opinion, but I digress).&lt;/p&gt;
&lt;p&gt;Anyway, what&amp;rsquo;s interesting with the Rust programming language is that we can express the spec in such a way that &lt;strong&gt;invalid states lead to compilation errors&lt;/strong&gt; and &lt;strong&gt;without using anything but structs and methods&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how. Since the specs talks about names that may or may not exist, we&amp;rsquo;re going to use two different types - one for the unnamed robots, and one for the robots that have a name. To be precise, those are called &lt;em&gt;structs&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// We wrap the robot name  inside a struct
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;NamedRobot&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;name: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// We create a brand new type for &amp;#34;robots that don&amp;#39;t have names&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;UnnamedRobot&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note : interestingly, this struct costs *nothing* to allocate and is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// known as a zero-sized type (ZST) in Rust parlance.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we can express the &lt;em&gt;transitions&lt;/em&gt; between allowed states as public methods on those types (inside a &lt;code&gt;impl&lt;/code&gt; block) or as free functions&lt;/p&gt;
&lt;p&gt;Note: that most of the bodies are omitted here, but you can find tho whole source code &lt;a href=&#34;https://github.com/dmerejkowsky/robots/blob/main/rust/src/lib.rs&#34;&gt;on github&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note: this is a private implementation detail, so no
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// `pub` here!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;generate_random_name&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new_robot&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;UnnamedRobot&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;UnnamedRobot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note: emit a compiler warning if users call start() without
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// using the return value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[must_use]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;NamedRobot&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;generate_random_name();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;NamedRobot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;NamedRobot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;stop&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note: taking ownership of `self` here!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;reset&lt;/span&gt;(self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;UnnamedRobot&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Valid code compiles of course:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;new_robot();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.start();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;println!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;New robot with name: &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{name}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And invalid code won&amp;rsquo;t compile. For instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;new_robot();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name()&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Error: method name() not found for UnnamedRobot
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can reset a robot, restart it and get a new name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;new_robot();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.start();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name1&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name().to_string();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.reset();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.start();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name2&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name().to_string();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;assert_ne!(name1,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name2);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may wondering why we need &lt;code&gt;.to_string()&lt;/code&gt; here. Well, let me explain.&lt;/p&gt;
&lt;h1 id=&#34;owning-and-borrowing&#34;&gt;Owning and borrowing&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#owning-and-borrowing&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I mentioned earlier that &lt;code&gt;reset&lt;/code&gt; &lt;em&gt;takes ownership&lt;/em&gt; of the robot.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s because the method uses &lt;code&gt;self&lt;/code&gt; as first parameter.&lt;/p&gt;
&lt;p&gt;In contrast, the &lt;code&gt;name&lt;/code&gt; method uses &lt;code&gt;&amp;amp;self&lt;/code&gt; and &lt;em&gt;borrows&lt;/em&gt; the robot.&lt;/p&gt;
&lt;p&gt;This matters because in addition to having a rich type system as we saw above,
the Rust compiler also enforce rules about ownership.&lt;/p&gt;
&lt;p&gt;Here are those rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Each value in Rust has an owner.&lt;/li&gt;
&lt;li&gt;There can only be one owner at a time.&lt;/li&gt;
&lt;li&gt;At any given time, you can have either &lt;strong&gt;one mutable&lt;/strong&gt; reference or any
number of &lt;strong&gt;immutable&lt;/strong&gt; references.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What this means is that when the robot is started, you can access the robot name any time
you want, as long as you don&amp;rsquo;t try to modify it. &lt;em&gt;But&lt;/em&gt;, once &lt;code&gt;reset()&lt;/code&gt; is called, the value
has been moved, and thus you can no longer access the robot name.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s this in practice:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;new_robot();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.start();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name1&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name().to_string();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name2&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name().to_string();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;robot.reset();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;name3&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;robot.name();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// Error: value `robot`  moved during called to reset reset()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If Rust had allowed this code to compile, we would have a &lt;code&gt;name3&lt;/code&gt; variable &lt;em&gt;after&lt;/em&gt;
the robot has been reset, which is not allowed by our spec!&lt;/p&gt;
&lt;p&gt;Note that this also means we can&amp;rsquo;t have &lt;code&gt;name1&lt;/code&gt; and &lt;code&gt;name2&lt;/code&gt; be merely string references (&lt;code&gt;&amp;amp;str&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why we use the &lt;code&gt;.to_string()&lt;/code&gt; method, which gives us as a &lt;em&gt;mutable copy&lt;/em&gt; (a &lt;code&gt;String&lt;/code&gt;) for the robot name.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you learn Rust, you&amp;rsquo;ll find that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;rsquo;s more to Object-Oriented Programming than just classes&lt;/li&gt;
&lt;li&gt;The borrow checker, when used well, can prevent a bunch of mistakes &lt;strong&gt;at compile time&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Side note: I used two different types to make a point. You will find a more idiomatic version of the code in the &lt;a href=&#34;https://github.com/dmerejkowsky/robots/blob/idiomatic/rust/src/lib.rs&#34;&gt;aptly named &amp;ldquo;idiomatic&amp;rdquo; branch on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The again show again how the borrow checker rules prevent invalid states &lt;em&gt;at compile time&lt;/em&gt;, this time because some methods (like &lt;code&gt;start&lt;/code&gt; or &lt;code&gt;reset&lt;/code&gt;) use &lt;code&gt;&amp;amp;mut self&lt;/code&gt; and other just &lt;code&gt;&amp;amp;self&lt;/code&gt; (like &lt;code&gt;name&lt;/code&gt;). It also shows the &amp;ldquo;new type&amp;rdquo; pattern, in order to enforce robot name format at runtime.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Is Rust worth learning? Part 1: logs and secrets</title>
      <link>https://dmerej.info/blog/post/rust-secrets-and-logs/</link>
      <pubDate>Tue, 04 Jan 2022 10:11:47 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/rust-secrets-and-logs/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;A language that doesn&amp;rsquo;t affect the way you think about programming, is not worth knowing.
&amp;ndash; Alan J. Perlis - Yale University&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To see if Rust is worth trying, then, let me tell you a story - based on real events.&lt;/p&gt;
&lt;h1 id=&#34;logs-and-secrets&#34;&gt;Logs and secrets&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#logs-and-secrets&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s say you are writing a Java application that needs to make HTTP calls on an external API.&lt;/p&gt;
&lt;p&gt;To do this, you have a client class that implements a &lt;code&gt;call&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Client&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;authenticate&lt;/span&gt;(String appSecret) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;doRequest&lt;/span&gt;(String url) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;call&lt;/span&gt;(String appSecret, String url) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    authenticate(appSecret);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    doRequest(url);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that you need do send an &lt;code&gt;app secret&lt;/code&gt; along the url to make the call, hence the separate &lt;code&gt;authenticate()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;You also have a Config record to hold the configuration of the application:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; record &lt;span style=&#34;color:#447fcf&#34;&gt;Config&lt;/span&gt;(String appSecret, String url) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, you have a main class that reads the values from the environment, builds a Config and a Client instances and uses it to make calls:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;App&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;(String[] args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String appSecret = System.&lt;span style=&#34;color:#bbb&#34;&gt;getenv&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;APP_SECRET&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String url = System.&lt;span style=&#34;color:#bbb&#34;&gt;getenv&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;API_URL&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Config config = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; Config(appSecret, url);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Client client = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; Client();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    client.&lt;span style=&#34;color:#bbb&#34;&gt;call&lt;/span&gt;(config.&lt;span style=&#34;color:#bbb&#34;&gt;appSecret&lt;/span&gt;(), config.&lt;span style=&#34;color:#bbb&#34;&gt;url&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since logs are important, you also add a call to &lt;code&gt;logger.info()&lt;/code&gt; when making the call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;call&lt;/span&gt;(String appSecret, String url) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  authenticate(appSecret);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  logger.&lt;span style=&#34;color:#bbb&#34;&gt;info&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Making the call&amp;#34;&lt;/span&gt;); &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt;- new
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  doRequest(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;a-vulnerability-happens&#34;&gt;A vulnerability happens&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-vulnerability-happens&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You push the code into production, and some time later you get assigned to the following bug in the issue tracker:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;BUG: APP_SECRET found in the logs
SEVERITY : critical
PRIORITY : high

The logs sent by the application at startup contains the
APP_SECRET

...
INFO: config: Config[appSecret=s3cret, url=https://api.dev]
...
INFO: Making the call
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So you take a look at the code base, and sure enough, you find the problem: someone from an other team added a log containing the contents of the Config class:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// SomewhereElse.java
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;logger.&lt;span style=&#34;color:#bbb&#34;&gt;info&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;config:&amp;#34;&lt;/span&gt; + config.&lt;span style=&#34;color:#bbb&#34;&gt;toString&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sure, the bug is easy to fix. You can just remove the call to &lt;code&gt;logger.info&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But after thinking about it more, you decide to also override the &lt;code&gt;toString()&lt;/code&gt; method of the &lt;code&gt;Config&lt;/code&gt; struct so that the app secret is &lt;em&gt;always&lt;/em&gt; redacted:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;public record Config(...) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+  @Override
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+  public String toString() {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+    return String.format(&amp;#34;Config[appSecret:REDACTED, url:%s]&amp;#34;, this.url);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+  }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There. You can mark the bug as &amp;ldquo;fixed&amp;rdquo; and move to something else, like take a look at this new programming language called Rust &amp;hellip;&lt;/p&gt;
&lt;p&gt;A few hours later, here&amp;rsquo;s what you learned.&lt;/p&gt;
&lt;h1 id=&#34;ownership&#34;&gt;Ownership&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#ownership&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;First, Rust has this notion of &lt;em&gt;ownership&lt;/em&gt;: every piece of data must have exactly one owner. By default, data is &lt;em&gt;moved&lt;/em&gt; and can&amp;rsquo;t be used after the move.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;StringOwner&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;inner: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt;- note: fields are private by default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;s&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;::from(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Creates a new string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;owner&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;StringOwner&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;inner: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;s&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Move the string into
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;                                        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// the &amp;#39;StringOwner&amp;#39; struct
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;println!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;s);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Compile error: cannot use the string after it&amp;#39;s moved
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Second, if you don&amp;rsquo;t want to move the value, you have to &amp;ldquo;borrow&amp;rdquo; it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;borrow_the_string&lt;/span&gt;(s: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt; Note the &amp;#39;&amp;amp;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;s&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;::from(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Creates a new string
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;borrow_the_string(&amp;amp;s);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note the &amp;#39;&amp;amp;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;println!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;s);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// OK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a immutable (or shared) borrow: you won&amp;rsquo;t be able to modify the string.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve also learned about mutable (or exclusive) borrows. They would allow you to modify the string, but they are not relevant for this story.&lt;/p&gt;
&lt;h2 id=&#34;the-trait-system&#34;&gt;The trait system&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-trait-system&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You also learned that classes don&amp;rsquo;t exist in Rust. Instead, Rust uses &lt;em&gt;traits&lt;/em&gt;, and adds methods to structs using &lt;code&gt;impl&lt;/code&gt; blocks:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* in stuff.rs */&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// This says that the Stuffer trait
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// contains a method named do_stuff
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;trait&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Stuffer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;do_stuff&lt;/span&gt;(&amp;amp;self);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Foo&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// This says that Foo implements the Stuffer trait,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// and than compilation will fail if do_stuff() is not present
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// or has not the proper signature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Stuffer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Foo&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;do_stuff&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Implementation here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The trait must be in the scope where you are using it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;stuff::Foo;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;foo&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Foo::new():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;foo&lt;/span&gt;.do_stuff();&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Error: Stuffer trait is not in scope
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;stuff::Foo;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;stuff::Stuffer;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt;- new
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;foo&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Foo::new():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;foo&lt;/span&gt;.do_stuff();&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// OK: Stuffer trait is in scope
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;a-rewrite&#34;&gt;A rewrite&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-rewrite&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So, feeling adventurous, you decide to try and re-implement your application in Rust, just to feel like how the code would look like and if you can find a better way of handling the security issue you had to fix in Java.&lt;/p&gt;
&lt;p&gt;You start with the &lt;code&gt;Config&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Config&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;url: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;app_secret: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then you add the &lt;code&gt;Client class&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Client&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Client&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;authenticate&lt;/span&gt;(&amp;amp;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;app_secret: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;do_request&lt;/span&gt;(&amp;amp;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;url: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;call&lt;/span&gt;(app_secret: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;url: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;self.authenticate(app_secret);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;info!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Making the call&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;self.do_request(url);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, the main() function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;app_secret&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::env::var(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;APP_SECRET&amp;#34;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;url&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::env::var(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;API_URL&amp;#34;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;config&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Config&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;app_secret,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;url&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;client&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Client;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;client.call(config.app_secret,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;config.url);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;Well, that was easy&amp;rdquo; you think. &amp;ldquo;I wonder what people mean when they&amp;rsquo;re talking about &amp;lsquo;fighting the borrow checker&amp;rsquo;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Then you try to use &lt;code&gt;client.call&lt;/code&gt; a second time:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;client&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Client;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;client.call(config.app_secret,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;config.url);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;client.call(config.app_secret,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;config.url);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt;- new
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error[E0382]: use of moved value: `config.app_secret`
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  --&amp;gt; src/main.rs:27:17
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;23 |     client.call(config.app_secret, config.url);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |                 ----------------- value moved here
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;27 |     client.call(config.app_secret, config.url);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |                 ^^^^^^^^^^^^^^^^^ value used here after move
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;Oh, right&amp;rdquo;, I need to &amp;ldquo;borrow&amp;rdquo; the &lt;code&gt;app_secret&lt;/code&gt; and the &lt;code&gt;url&lt;/code&gt; in the client if I want to be able to keep using the config struct.&lt;/p&gt;
&lt;p&gt;So you change the code to be like this instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  impl Client {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-     fn call(&amp;amp;self, app_secret: String, url: String) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+     fn call(&amp;amp;self, app_secret: &amp;amp;str, url: &amp;amp;str) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;          //
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    client.call(config.app_secret, config.url);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+    client.call(&amp;amp;config.app_secret, &amp;amp;config.url);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There. Now the client &lt;em&gt;borrows&lt;/em&gt; the app secret and the url and the code compiles and runs fine.&lt;/p&gt;
&lt;p&gt;Feeling confident, you try and reproduce the logging issue.&lt;/p&gt;
&lt;p&gt;First, you add a &lt;code&gt;#[derive(Debug)]&lt;/code&gt; annotation on top of the &lt;code&gt;Config&lt;/code&gt; struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ #[derive(Debug)]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;  struct Config {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then you add a log displaying the contents of the config struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fn main() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    let config = Config { app_secret, url };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   info!(&amp;#34;config: {:?}&amp;#34;, &amp;amp;config);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;   }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code works because Rust knows how to print debug representations of strings and booleans and the &lt;code&gt;derive(Debug)&lt;/code&gt; annotation can automatically generates the code to print a debug representation of the &lt;code&gt;Config&lt;/code&gt; struct.&lt;/p&gt;
&lt;p&gt;Indeed, the code compile, and, sure enough, the secret shows up in the log:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[INFO] config: Config { app_secret: &amp;#34;s3cret&amp;#34;, url: &amp;#34;https://api.dev&amp;#34; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[INFO] Making the call to https://api.dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK, you&amp;rsquo;ve reproduced the problem. But can you find a better solution this time?&lt;/p&gt;
&lt;h1 id=&#34;time-to-think&#34;&gt;Time to think&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#time-to-think&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You&amp;rsquo;ve heard good things about Rust type system, so you wonder: &amp;ldquo;Would it be possible to solve the problem by adding a new type?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;You start with a &lt;code&gt;SecretString&lt;/code&gt; struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;SecretString&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;inner: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;SecretString&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(inner: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Self&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Self&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;inner&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The constructor takes ownership of the string, which is a good thing, because it means the inner value &lt;em&gt;can no longer be accessed&lt;/em&gt; once the &lt;code&gt;SecretString&lt;/code&gt; struct is created:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;secret_value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::env::var(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;APP_SECRET&amp;#34;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;app_secret&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;SecretString::new(secret_value):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;dbg&lt;/span&gt;!(secret_value);&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt; does not compile!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then you change the type of &lt;code&gt;app_secret&lt;/code&gt; in Config from &lt;code&gt;String&lt;/code&gt; to &lt;code&gt;SecretString&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;struct Config {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    app_secret: String,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+    app_secret: SecretString,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which means you have to get the inner value when authenticating the client:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;impl Client {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   fn call(&amp;amp;self, app_secret: &amp;amp;str, url: &amp;amp;str) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   self.authenticate(&amp;amp;app_secret);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   fn call(&amp;amp;self, app_secret: &amp;amp;SecretString, url: &amp;amp;str) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+      self.authenticate(app_secret.inner);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You are then faced with 2 compile errors:&lt;/p&gt;
&lt;p&gt;First, the &lt;code&gt;Debug&lt;/code&gt; macro no longer works:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error[E0277]: `SecretString` doesn&amp;#39;t implement `std::fmt::Debug`
  --&amp;gt; src/main.rs:26:5
   |
24 | #[derive(Debug)]
   |          ----- in this derive macro expansion
25 | struct Config {
26 |     app_secret: SecretString,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `SecretString` cannot be formatted using `{:?}`
   |
   = help: the trait `std::fmt::Debug` is not implemented for `SecretString`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To fix this, you implement the debug trait yourself:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::fmt::Debug;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ^-- new - remember: traits needs to be in scope
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// in order to use them
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Debug&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;SecretString&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;fmt&lt;/span&gt;(&amp;amp;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;f: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::fmt::Formatter&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;&amp;#39;_&lt;/span&gt;&amp;gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;std&lt;/span&gt;::fmt::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;write!(f,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;REDACTED&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Second, you can&amp;rsquo;t use the &lt;code&gt;inner&lt;/code&gt; field directly in the &lt;code&gt;call()&lt;/code&gt; method:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error[E0616]: field `inner` of struct `SecretString` is private
  --&amp;gt; src/client.rs:13:39
   |
13 |         let secret_value = app_secret.inner;
   |                                       ^^^^^ private field
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So you add a public method to access the inner value:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;SecretString&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;expose_value&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&amp;amp;self.inner&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And you fix the client code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;call&lt;/span&gt;(&amp;amp;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;app_secret: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;SecretString&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;url: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;secret_value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;app_secret.expose_value();&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt;- new!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;self.authenticate(&amp;amp;secret_value);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;going-further&#34;&gt;Going further&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#going-further&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Then you think back about the rule about traits having to be in scope, and you decide to move the &lt;code&gt;expose_value&lt;/code&gt; method into a trait:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;trait&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;ExposeSecret&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;expose_value&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;ExposeSecret&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;SecretString&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ^--  used to be `impl SecretString`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;expose_value&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&amp;amp;self.inner&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then the compiler says:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error[E0599]: no method named `expose_value` found for reference
`&amp;amp;SecretString` in the current scope
  --&amp;gt; src/client.rs:13:39
   |
13 |         let secret_value = app_secret.expose_value();
   |                                       ^^^^^^^^^^^^

   = help: items from traits can only be used if the trait is in scope
   = help: the following trait is implemented but not in scope; perhaps add a
           `use` for it:

use crate::secrets::ExposeSecret;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So you comply:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;crate&lt;/span&gt;::secrets::ExposeSecret;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// &amp;lt;- new!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;crate&lt;/span&gt;::secrecy::SecretString;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There - the code compiles, and it&amp;rsquo;s now pretty hard to leak the app secret:&lt;/p&gt;
&lt;p&gt;Indeed, if a value has been wrapped in the SecretString struct, anyone attempting to access it must:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;call a method that &lt;em&gt;sounds&lt;/em&gt; dangerous (&lt;code&gt;expose_value()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;import a trait that &lt;em&gt;also&lt;/em&gt; sounds dangerous (&lt;code&gt;secrets::ExposeSecret&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s also very easy to edit the code for safety: just list the usages of the &lt;code&gt;ExposeSecret&lt;/code&gt; trait.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I hope you found this post interesting: it shows how you can use some unique features of the Rust programming language to tackle an old issue in a novel way.&lt;/p&gt;
&lt;p&gt;I mentioned at the beginning that the this post is based on true stories, so here are my two sources of inspiration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The issue of a secret value exposed by mistake is based on an actual security vulnerability I reported to the Miniflux maintainers. You can see the details in the &lt;a href=&#34;https://github.com/miniflux/v2/commit/87d58987a698296fa4306ed43e8400568edd51f1&#34;&gt;miniflux repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;SecretString&lt;/code&gt; struct is based on a real crate, called &lt;a href=&#34;https://docs.rs/secrecy/latest/secrecy/&#34;&gt;secrecy&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks for taking this journey with me, and if you&amp;rsquo;re a reading this while trying to fix the log4j security vulnerability, you have my sincere sympathy :)&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Merge first, ask questions later - Optimistic Merging in practice</title>
      <link>https://dmerej.info/blog/post/optimistic-merging/</link>
      <pubDate>Tue, 14 Sep 2021 14:06:46 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/optimistic-merging/</guid>
      <description>&lt;h1 id=&#34;introduction---pessimistic-merging&#34;&gt;Introduction - Pessimistic Merging&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction---pessimistic-merging&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;If you&amp;rsquo;ve contributed to an open-source project on GitHub or GitLab, or written code for a company, you&amp;rsquo;re probably familiar with the concept of &amp;ldquo;Pessimistic Merging&amp;rdquo;. You write a patch (or a pull request or a merge request), but it is not merged (or applied) right away. Instead, you need to wait for human approval to be given and/or for continuous integration to pass.&lt;/p&gt;
&lt;p&gt;I can think of two reasons why this strategy is often the one which is used:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It&amp;rsquo;s been used by really big projects (like the Linux kernel) for quite some time&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s kind of the &lt;em&gt;default&lt;/em&gt; way to collaborate on platforms like GitHub or GitLab&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are even tools like Gerrit which work by specifying a list of constraints before a patch can be merged &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; - which is used among other things by Google&amp;rsquo;s Android Open Source Project or the Qt framework.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s also the fact that it allows to enforce some rules. Used in combination with source control software (like Git), Pessimistic Merging can ensure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &amp;ldquo;clean&amp;rdquo; git history (from the commit messages to their contents to the size of the patches)&lt;/li&gt;
&lt;li&gt;A consistent coding style&lt;/li&gt;
&lt;li&gt;A test suite that always pass on the main development branch&lt;/li&gt;
&lt;li&gt;A code that is composed only of patches that have been reviewed and approved by an arbitrary number of people&lt;/li&gt;
&lt;li&gt;&amp;hellip; and so on&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And indeed, there are some projects where this matters a lot - in a corporate environment, or in a &amp;ldquo;sensitive&amp;rdquo; project like a browser, a database engine or an operating system &amp;hellip;&lt;/p&gt;
&lt;p&gt;That being said, we rarely talk about the &lt;em&gt;downsides&lt;/em&gt; of Pessimistic Merging - which is why you probably never thought that this concept needed a &lt;em&gt;name&lt;/em&gt;.&lt;/p&gt;
&lt;h1 id=&#34;issues-with-pessimistic-merging&#34;&gt;Issues with Pessimistic Merging&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#issues-with-pessimistic-merging&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For this, I&amp;rsquo;ll let you read the article which prompted me to write this one: &lt;a href=&#34;http://hintjens.com/blog:106&#34;&gt;Why Optimistic Merging Works Better&lt;/a&gt; &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;The idea behind Optimistic Merging is very simple: you &lt;em&gt;merge the patch first&lt;/em&gt;, and &lt;em&gt;then&lt;/em&gt; deal with issues like broken builds, code style violation and other problems.&lt;/p&gt;
&lt;p&gt;Sure, this means that the main development branch of your Git repository may now contain commits that do not fully work, code that does not always compile, or commits that only fix code styling errors.&lt;/p&gt;
&lt;p&gt;But for a small or medium-sized project, that does nothing too security-sensitive, and for which maintainers and collaborators are hard to find - is it such a bad deal?&lt;/p&gt;
&lt;p&gt;On this topic, see also Aleksey Kladov&amp;rsquo;s piece on &lt;a href=&#34;https://matklad.github.io/2021/01/03/two-kinds-of-code-review.html&#34;&gt;Two Kinds of Code Review&lt;/a&gt; (which is the reason I learned about Optimistic Merging in the first place and wanted to try it out), where he explains how pull requests are reviewed and merged for the rust-analyzer project.&lt;/p&gt;
&lt;p&gt;A note before I continue: they are plenty of cases where using Pessimistic Merging &lt;em&gt;is&lt;/em&gt; the best strategy - here I&amp;rsquo;m just describing an alternate strategy you may find interesting.&lt;/p&gt;
&lt;p&gt;With that out of the way, let&amp;rsquo;s now look how Optimistic Merging works for me in practice.&lt;/p&gt;
&lt;h2 id=&#34;my-workflow-for-optimistic-merging&#34;&gt;My workflow for Optimistic Merging&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#my-workflow-for-optimistic-merging&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&#34;setting-the-stage&#34;&gt;Setting the stage&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#setting-the-stage&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m the maintainer of a project called &amp;ldquo;foo&amp;rdquo;, written in Python, and hosted in GitHub.&lt;/p&gt;
&lt;p&gt;The project uses &lt;code&gt;flake8&lt;/code&gt; as a linter to catch small mistakes, the code is formatted with &lt;code&gt;black&lt;/code&gt;, and it has has some tests (of course). It is also &lt;em&gt;very easy&lt;/em&gt; to run the linters, the tests and the code formatter from the developer machine (this will matter later on).&lt;/p&gt;
&lt;p&gt;Here comes a developer I never heard of (let&amp;rsquo;s call them Mallory) - and they open their first ever merge request to the GitHub repository.&lt;/p&gt;
&lt;h3 id=&#34;merging-mallorys-changes&#34;&gt;Merging Mallory&amp;rsquo;s changes&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#merging-mallorys-changes&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first step is for me to get the proposed changes on my machine and to prepare a list of notes for later feedback - a simple text file is enough.&lt;/p&gt;
&lt;p&gt;Since it&amp;rsquo;s a PR on GitHub, I can do something like this, where &amp;ldquo;some-branch&amp;rdquo; is the &lt;em&gt;source ref&lt;/em&gt; of Mallory&amp;rsquo;s PR:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git remote add mallory git@github.com:mallory/foo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ git fetch mallory
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;From github.com:mallory/foo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;* [new branch] some-branch -&amp;gt; mallory/some-branch
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I rebase &lt;code&gt;some-branch&lt;/code&gt; on top of the main branch. This allows me to make sure the commits can be merged without conflicts.&lt;/p&gt;
&lt;p&gt;During the rebase I look at each commit diff and I take notes.&lt;/p&gt;
&lt;p&gt;Since everything is on my machine, it&amp;rsquo;s trivial to amend Mallory&amp;rsquo;s commits if a linter complains or to run &lt;code&gt;black&lt;/code&gt; if I need to.&lt;/p&gt;
&lt;p&gt;I can also choose to run the tests locally if I fear a commit may have caused a regression.&lt;/p&gt;
&lt;p&gt;Finally, if there&amp;rsquo;s a small issue (like a misleading comment) I can fix it right away! There&amp;rsquo;s no need to go through the hassle of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;telling Mallory they did something wrong,&lt;/li&gt;
&lt;li&gt;waiting for them to update the merge request,&lt;/li&gt;
&lt;li&gt;re-starting the process from scratch.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When all of this is done, it&amp;rsquo;s time to push Mallory&amp;rsquo;s branch. I re-run the linters and the tests just to be sure, then I push the code and leave a message in the PR discussion telling Mallory the changes have been merged.&lt;/p&gt;
&lt;h3 id=&#34;looking-at-the-interaction-from-mallorys-point-of-view&#34;&gt;Looking at the interaction from Mallory&amp;rsquo;s point of view&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#looking-at-the-interaction-from-mallorys-point-of-view&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s very likely that Mallory was not paid to write the patch, (this is a medium-size open-source project, after all) but they still worked on it and thought their work was good enough to open a pull request.&lt;/p&gt;
&lt;p&gt;They probably don&amp;rsquo;t know much about the project, and it&amp;rsquo;s likely they don&amp;rsquo;t know everything about Git, Python, flake8 or black. And it&amp;rsquo;s even possible they know nothing about testing!&lt;/p&gt;
&lt;p&gt;Yet, the first reply they got for the maintainer is &amp;ldquo;Thanks! Your commits have been merged&amp;rdquo;. Boom - the collaboration is already working - what a great start!&lt;/p&gt;
&lt;p&gt;Contrast with a typical response when using Pessimistic Merging,  which would look like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thank you for your contribution, but the CI does not pass (test_foo_bar4 is failing and there are some lint errors). Also, please merge or rebase your work on top of the main branch so that the merge is fast-forward.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;hellip; followed by a bunch of nitpicks about the merge request.&lt;/p&gt;
&lt;h3 id=&#34;after-the-merge&#34;&gt;After the merge&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#after-the-merge&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Anyway, now it&amp;rsquo;s time to put my notes to good use.&lt;/p&gt;
&lt;p&gt;If there are some trivial changes I had to do, I can just tell Mallory:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It was a good idea to refactor the do_stuff() method inside the Foo class, but you did not adapt the doc string, which I&amp;rsquo;ve done in commit &amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Again, we&amp;rsquo;re &lt;em&gt;working together&lt;/em&gt; here, and I&amp;rsquo;m willing to bet Mallory is more likely to watch their docstrings next time they write a new patch :)&lt;/p&gt;
&lt;p&gt;If there was some non-trivial changes (like a missed opportunity for a refactoring), I can just create an issue with a task list for instance.&lt;/p&gt;
&lt;p&gt;I can also start a pull request and have &lt;em&gt;Mallory&lt;/em&gt; review it.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To be frank, I&amp;rsquo;ve just started implementing this strategy for my open-source projects, so it&amp;rsquo;s a bit early to draw any conclusions. That being said, so far it has been going great, and I wanted to share the idea of Optimistic Merging right way.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll let you know how it goes in the future. Until then, happy coding!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Fun fact: to do this,  Gerrit embeds &lt;a href=&#34;https://gerrit-review.googlesource.com/Documentation/prolog-cookbook.html&#34;&gt;an implementation of the Prolog Language&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;If you have trouble with opening this link, make sure you are using the http:// URL, the https:// version is  unfortunately broken.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Two awesome Rust warnings</title>
      <link>https://dmerej.info/blog/post/awesome-rust-warnings/</link>
      <pubDate>Tue, 02 Feb 2021 13:35:21 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/awesome-rust-warnings/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;If you&amp;rsquo;ve ever used a compiler (or any other tool) that can produce warnings about your code, you may be used to messages that are hard to understand, confusing or just plain wrong.&lt;/p&gt;
&lt;p&gt;But today I want to show you that good compiler warnings do exist and how they can make your code more correct.&lt;/p&gt;
&lt;h1 id=&#34;the-incorrect-server-api&#34;&gt;The incorrect server API&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-incorrect-server-api&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The first example comes from code I wrote to test the Rust implementation of the Tanker client SDK. You don&amp;rsquo;t need to know precisely how Tanker works to follow this example - let&amp;rsquo;s just say the client needs a &amp;ldquo;Tanker permanent identity&amp;rdquo; from an identity server to start a session.&lt;/p&gt;
&lt;p&gt;In my case, the identity server was already written in Go using the Gin-Gonic framework.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the implementation of the &lt;code&gt;sign_in&lt;/code&gt; route looked like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// This struct is used by various Gin handlers
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;type&lt;/span&gt; UserResponse &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	UserID              &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;`json:&amp;#34;user_id&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	Email               &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;`json:&amp;#34;email&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	PermanentIdentity   &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;`json:&amp;#34;tanker_permanent_identity&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// handler for the /sign_in route
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;func&lt;/span&gt; (this *Server) &lt;span style=&#34;color:#447fcf&#34;&gt;signIn&lt;/span&gt;(c *gin.Context) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;var&lt;/span&gt; body SignInBody
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	jsonErr := c.&lt;span style=&#34;color:#447fcf&#34;&gt;BindJSON&lt;/span&gt;(&amp;amp;body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; jsonErr != &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		c.&lt;span style=&#34;color:#447fcf&#34;&gt;JSON&lt;/span&gt;(&lt;span style=&#34;color:#3677a9&#34;&gt;400&lt;/span&gt;, gin.H{&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;: jsonErr.&lt;span style=&#34;color:#447fcf&#34;&gt;Error&lt;/span&gt;()})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	email := body.Email
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	password := body.Password
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Not shown: check email and password, fetch user from the db
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	userResponse := UserResponse{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		Email:               user.Email,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		UserID:              user.UserID,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		PermanentIdentity:   user.PermanentIdentity,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	c.&lt;span style=&#34;color:#447fcf&#34;&gt;JSON&lt;/span&gt;(&lt;span style=&#34;color:#3677a9&#34;&gt;200&lt;/span&gt;, userResponse)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To parse the JSON response from the server in the Rust client, I used serde, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Deserialize)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;UserResponse&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;user_id: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;email: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;tanker_permanent_identity: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Client&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;async&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;sign_in&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;email&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;...;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;password&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;...;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;data&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;HashMap::new();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;data.insert(&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;::from(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;),&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;email);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;data.insert(&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;::from(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;password&amp;#34;&lt;/span&gt;),&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;password);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;response&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.client.post(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/sign_in&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;data).&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;await&lt;/span&gt;?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;user_response&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;response.json::&amp;lt;UserResponse&amp;gt;().&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;await&lt;/span&gt;?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.start_tanker(&amp;amp;user_response).&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;await&lt;/span&gt;?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;async&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start_tanker&lt;/span&gt;(&amp;amp;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;user_response: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;UserResponse&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;private_identity&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;user_response.tanker_permanent_identity;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;email&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;user_response.email;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;status&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.tanker.start(&amp;amp;private_identity).&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;await&lt;/span&gt;?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Not shown: verify identity by email when required
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When I first compiled the code, I got this warning:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Warning: field is never read: `user_id`
  --&amp;gt; src/notepad.rs:24:5
   |
24 |     user_id: String,
   |     ^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This made sense: as you can see, to start a Tanker session we only need the &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;tanker_permanent_identity&lt;/code&gt; fields of the JSON response returned by the server. In particular, we don&amp;rsquo;t need the user ID at all.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s interesting with this example is that at Tanker, we already wrote &lt;em&gt;six other clients&lt;/em&gt; for the server in question (using Python, Go, Java, JavaScript, Objective-C and Ruby) and that was the first time we got an indication that our JSON API was wasting bandwidth by sending information that was actually not needed!&lt;/p&gt;
&lt;h1 id=&#34;the-useless-mutation&#34;&gt;The useless mutation&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-useless-mutation&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The second example comes from a personal project - a week ago I started implementing an interpreter in Rust, following the instructions from the &lt;a href=&#34;https://interpreterbook.com/&#34;&gt;Writing an Interpreter in Go&lt;/a&gt;, by Throsten Ball.&lt;/p&gt;
&lt;p&gt;As I worked on the the lexer, I wrote the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::iter::Peekable;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;::CharIndices;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;crate&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Lexer&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;code: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;iter: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Peekable&lt;/span&gt;&amp;lt;CharIndices&amp;lt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt;&amp;gt;&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Lexer&amp;lt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(code: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Self&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Self&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;iter: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;code&lt;/span&gt;.char_indices().peekable(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;code,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;/// Try to read an identifier starting at start_pos
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;read_identifier&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;start_pos: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;usize&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&amp;#39;a&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// end_pos is either `None` if we reached the end of the input code,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// or Some(index) if we reached a character that is not part of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// of a valid identifier
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;end_pos&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(start_pos);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Is the next character valid?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;peek&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.iter.peek();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;peek&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;((next_pos,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;next_c))&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Self::is_valid_ident(*next_c)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Yes: advance next_pos
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;end_pos&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(*next_pos);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;self.iter.next();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;((next_pos,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;_))&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// No: advance next_pos and exit the loop
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;end_pos&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(*next_pos);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;break&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;None&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// There&amp;#39;s no next character : we&amp;#39;ve reached the end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// of the input code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;end_pos&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;None&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;break&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;end_pos&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// end_pos is None: return all the code from start_pos to the end
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;None&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;self.code[start_pos..],&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// end_pos is not None: return the code from start_pos to end_pos
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(index)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;self.code[start_pos..index],&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s what the compiler had to say:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;warning: value assigned to `end_pos` is never read
   --&amp;gt; src/lexer.rs:131:13
    |
131 |         let mut end_pos = Some(start_pos);
    |             ^^^^^^^^^^^
    |
    = note: `#[warn(unused_assignments)]` on by default
    = help: maybe it is overwritten before being read?

warning: value assigned to `end_pos` is never read
   --&amp;gt; src/lexer.rs:136:21
    |
136 |                     end_pos = Some(*next_pos);
    |                     ^^^^^^^
    |
    = help: maybe it is overwritten before being read?
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The second warning was the easiest to fix: we keep setting &lt;code&gt;end_pos&lt;/code&gt; to
&lt;code&gt;Some(*next_pos)&lt;/code&gt; but never read it until the loop exits. So we can just
remove the line that sets &lt;code&gt;end_pos&lt;/code&gt; before calling &lt;code&gt;self.iter.next()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fn read_identifier(&amp;amp;mut self, start_pos: usize) -&amp;gt; &amp;amp;&amp;#39;a str {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        let mut end_pos = Some(start_pos);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        loop {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              match peek {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-                 Some((next_pos, next_c)) if Self::is_valid_ident(*next_c) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-                     end_pos = Some(*next_pos);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+                 Some((_, next_c)) if Self::is_valid_ident(*next_c) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;                      self.iter.next();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  Some((next_pos, _)) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      end_pos = Some(*next_pos);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      break;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  None =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      end_pos = None;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      break;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But the compiler was still unhappy:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;warning: value assigned to `end_pos` is never read
   --&amp;gt; src/lexer.rs:131:13
    |
131 |         let mut end_pos = Some(start_pos);
    |             ^^^^^^^^^^^
    |
    = note: `#[warn(unused_assignments)]` on by default
    = help: maybe it is overwritten before being read?
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This took me a while to realize, but the compiler is telling me that I can
declare the &lt;code&gt;end_pos&lt;/code&gt; binding but not initialize it right away:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fn read_identifier(&amp;amp;mut self, start_pos: usize) -&amp;gt; &amp;amp;&amp;#39;a str {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-       let mut end_pos = Some(start_pos);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+       let end_pos;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;        loop {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              match peek {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  Some((_, next_c)) if Self::is_valid_ident(*next_c) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      end_pos = Some(*next_pos);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      self.iter.next();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  Some((next_pos, _)) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      end_pos = Some(*next_pos);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      break;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  None =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      end_pos = None;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      break;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I love this : the &lt;code&gt;end_pos&lt;/code&gt; binding is no longer &lt;code&gt;mut&lt;/code&gt;, and can &lt;em&gt;only&lt;/em&gt; be assign a value in two cases:
either in the &lt;code&gt;None&lt;/code&gt; arm of the &lt;code&gt;match peek&lt;/code&gt; block, or to &lt;code&gt;end_pos&lt;/code&gt; when the peek character is not valid.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s much less likely for the code to be buggy!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I hope those two examples gave you an idea of what it&amp;rsquo;s like to write code using a language
that has such a focus on &lt;em&gt;correctness&lt;/em&gt; and how nice it is to have &lt;em&gt;useful&lt;/em&gt; warnings.&lt;/p&gt;
&lt;p&gt;For now, Rust is the only language I&amp;rsquo;ve used which gave me this feeling of &amp;ldquo;the compiler has my back&amp;rdquo;,
but I&amp;rsquo;m sure they are others - please tell me bellow if you know one.&lt;/p&gt;
&lt;p&gt;And if this gave you a motivation to try and learn Rust, go for it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>dmerej.info: now on the Gemini space</title>
      <link>https://dmerej.info/blog/post/dmerej-info-now-on-the-gemini-space/</link>
      <pubDate>Thu, 19 Nov 2020 16:10:22 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/dmerej-info-now-on-the-gemini-space/</guid>
      <description>&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;Just a quick note to let you know my personal website is now available on the Gemini space too.&lt;/p&gt;
&lt;p&gt;Get a &lt;a href=&#34;https://gemini.circumlunar.space/clients.html&#34;&gt;Gemini client&lt;/a&gt; and see you at &lt;a href=&#34;gemini://dmerej.info&#34;&gt;gemini://dmerej.info&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But Why?&lt;/p&gt;
&lt;h1 id=&#34;1-because-i-can&#34;&gt;1. Because I can&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#1-because-i-can&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Because I can! - classic geeky answer I know.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been hosting my own server on the Web for quite some time, and it&amp;rsquo;s much, much easier to set up a Gemini server. So, feel free to give it a go yourself.&lt;/p&gt;
&lt;h1 id=&#34;2-because-of-what-gemini-stands-for&#34;&gt;2. Because of what Gemini stands for&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#2-because-of-what-gemini-stands-for&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The second reason is that I like what Gemini stands for.&lt;/p&gt;
&lt;p&gt;As per the FAQ:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Gemini may be of interest to people who are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opposed to the web&amp;rsquo;s ubiquitous user tracking&lt;/li&gt;
&lt;li&gt;Tired of obnoxious adverts, auto-playing videos and other misfeatures&lt;/li&gt;
&lt;li&gt;Interested in low-power computing and/or low-speed networks&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;m interested in the first two for philosophical and political reasons.
I care a bit less about the last one, but it&amp;rsquo;s a nice touch (think of
the environmental reasons).&lt;/p&gt;
&lt;h1 id=&#34;3-to-produce-more-content&#34;&gt;3. To produce more content&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#3-to-produce-more-content&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To cite the FAQ:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Gemini already has a surprising number of client and server implementations in existence [&amp;hellip;], but the real shortage right now is not of software but of content [&amp;hellip;] The greatest contribution you can make to the project is to be a part of this process.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, enjoy about 100 articles spanning 4 years!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>&#34;It&#39;s a waste of time!&#34;</title>
      <link>https://dmerej.info/blog/post/its-not-a-waste-of-time/</link>
      <pubDate>Sat, 30 May 2020 10:18:46 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/its-not-a-waste-of-time/</guid>
      <description>&lt;p&gt;I have a confession to make: every time I heard the phrase &amp;ldquo;It&amp;rsquo;s a waste of time!&amp;rdquo;, I get a little angry.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve heard this answer countless times, often after suggestions like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Let&amp;rsquo;s write tests before writing production code.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Let&amp;rsquo;s write documentation before writing code.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Let&amp;rsquo;s refactor before implementing the new feature.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Let&amp;rsquo;s discuss the API once more before shipping the next release.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are several reasons why I don&amp;rsquo;t like this answer.&lt;/p&gt;
&lt;p&gt;Why? It&amp;rsquo;s all about knowledge.&lt;/p&gt;
&lt;h1 id=&#34;time-spent-vs-time-saved&#34;&gt;Time spent vs. time saved&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#time-spent-vs-time-saved&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;First, it&amp;rsquo;s easy to see the time &lt;em&gt;spent&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Yes, we spent one week writing and reviewing the new documentation. Yes, we spent three days refactoring the code, and we did not implement any feature. Yes, we had two one-hour meetings before getting a consensus on the new API and shipping the next release.&lt;/p&gt;
&lt;p&gt;But it&amp;rsquo;s tough to see the time &lt;em&gt;saved&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Who knows what horrible bug we would have to fix in production if we skipped writing those tests? Who knows how much breaking changes we would have made because the API was not good enough? Who knows how much time we would have spent implementing the &lt;em&gt;next&lt;/em&gt; big feature if we skipped the refactoring?&lt;/p&gt;
&lt;h1 id=&#34;learning-about-the-problem&#34;&gt;Learning about the problem&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#learning-about-the-problem&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Second, you may have noticed that in all the situations I mentioned above, it&amp;rsquo;s all about gaining more knowledge about the problem &lt;em&gt;before&lt;/em&gt; jumping to the implementation.&lt;/p&gt;
&lt;p&gt;In other words, by saying: &amp;ldquo;It&amp;rsquo;s a waste of time,&amp;rdquo; you assume you know enough about the problem to start working on the implementation right away.&lt;/p&gt;
&lt;h1 id=&#34;trying-to-convince-others&#34;&gt;Trying to convince others&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#trying-to-convince-others&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Most of the time, I can&amp;rsquo;t convince people who tell me that I&amp;rsquo;m suggesting  is a waste of time.&lt;/p&gt;
&lt;p&gt;Instead, they skip what I think was a critical preparatory step, and then I watch them spend a ton of time rectifying the situation afterward - it&amp;rsquo;s frustrating.&lt;/p&gt;
&lt;p&gt;Fortunately, after they&amp;rsquo;ve repeated the same mistake enough times, they tend to listen to me at last. But I&amp;rsquo;d very much like not to have to go through this painful process every time.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not sure what to do about it, though. Maybe it&amp;rsquo;s just human nature?&lt;/p&gt;
&lt;p&gt;To make matters worse, sometimes writing the code &lt;em&gt;is&lt;/em&gt; a good way to gain this precious knowledge in a way that neither tests nor documentation nor brainstorms could have done.&lt;/p&gt;
&lt;h1 id=&#34;questions-for-you&#34;&gt;Questions for you&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#questions-for-you&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;What do you think about all this? How do you react when confronted with the &amp;ldquo;It&amp;rsquo; a waste of time!&amp;rdquo; argument?&lt;/p&gt;
&lt;p&gt;Feel free to share your ideas below, and see you next time!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tips for better Python tests</title>
      <link>https://dmerej.info/blog/post/python-tests-tips/</link>
      <pubDate>Sat, 25 Apr 2020 14:20:47 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/python-tests-tips/</guid>
      <description>&lt;p&gt;Today, I&amp;rsquo;d like to share with you a list of small tips to help you write better tests when using Python. Note that the tips often improve both the readability of the test implementation, &lt;em&gt;and&lt;/em&gt; of the failure messages (which is pretty important too).&lt;/p&gt;
&lt;h1 id=&#34;use-pytest&#34;&gt;Use pytest&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#use-pytest&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Pytest does a great job in generating very good error messages from your assertions, without the need for anything other than the &lt;code&gt;assert&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;Take this assertion for instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; foo(x) == bar(y)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s what the failure will look like when using &lt;code&gt;pytest&lt;/code&gt; if the assertion fails:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    def test_foobar():
        x = 2
&amp;gt;       assert foo(x) == bar(x)
E       assert 4 == 5
E        +  where 4 = foo(2)
E        +  and   5 = bar(2)

test.py:11: AssertionError
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note how much information you get about what went wrong, like the entire body of the function up to the assertion that failed, or when the values that were compared came from.&lt;/p&gt;
&lt;p&gt;It gets even better - take this other assertion:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; get_message() == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;this is what I expected&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And note the nice, detailed diff between the two strings that gets printed:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    def test_get_message():
&amp;gt;       assert get_message() == &amp;#34;this is what I expected&amp;#34;
E       AssertionError: assert &amp;#39;this is what I expected&amp;#39; == &amp;#39;this is what I got&amp;#39;
E         - this is what I expected
E         ?                ^^^^^ --
E         + this is what I got
E         ?                ^^^
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;a-more-complex-example&#34;&gt;A more complex example&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-more-complex-example&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For the rest of this post, let&amp;rsquo;s assume you are testing a &lt;code&gt;sync_folders()&lt;/code&gt; function that can synchronize a remote folder with a local one.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s one of the tests you wrote:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_can_update_local_file&lt;/span&gt;(remote, local):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    local_file  = local / &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;a.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    local_file.write_text(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;old contents&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    new_contents = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;new contents&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    remote.add_file(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;a.txt&amp;#34;&lt;/span&gt;, contents=new_contents)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sync_folders(remote, local)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    actual_contents = local_file.read_text()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; actual_contents == new_contents
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Quick tip: I usually split my tests into three &lt;em&gt;arrange&lt;/em&gt; /&lt;em&gt;act&lt;/em&gt; / &lt;em&gt;assert&lt;/em&gt; parts and I visualize them using vertical space&lt;/em&gt;.&lt;/p&gt;
&lt;h1 id=&#34;add-context-to-assertions&#34;&gt;Add context to assertions&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#add-context-to-assertions&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Did you know you can add a string at the end of the &lt;code&gt;assert&lt;/code&gt; statement?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;def test_sync(remote, local):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    actual_contents = local_file.read_text()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   assert actual_contents == new_contents&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   assert actual_contents == new_contents, &amp;#34;a.txt should have been updated&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way, instead of having to read this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;E       AssertionError: assert &amp;#39;old contents\n&amp;#39; == &amp;#39;new contents&amp;#39;
E         - old contents
E         + new contents
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;you get this message, which contains a clue about where the diff actually comes from:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;E       AssertionError: a.txt should have been updated
E       assert &amp;#39;old contents\n&amp;#39; == &amp;#39;new contents&amp;#39;
E         - old contents
E         + new contents
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;reduce-noise&#34;&gt;Reduce noise&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#reduce-noise&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You can also improve the signal over noise ratio by using &lt;code&gt;pytest.fail&lt;/code&gt; instead of the &lt;code&gt;assert&lt;/code&gt; statement:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-  assert actual_contents == new_contents&amp;#34;, &amp;#34;a.txt should have been updated&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+  if actual_contents != new_contents:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+      pytest.fail(&amp;#34;a.txt should have been updated&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;        if actual_contents != new_contents:
&amp;gt;           pytest.fail(&amp;#34;a.txt should have been updated&amp;#34;)
E           Failed: a.txt should have been updated```
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Be careful when using this technique, because it may hinder the debugging of failing tests.&lt;/p&gt;
&lt;h1 id=&#34;use-custom-assertion-helpers&#34;&gt;Use custom assertion helpers&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#use-custom-assertion-helpers&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Finally, don&amp;rsquo;t hesitate to factorize code about assertions, for instance in a &lt;code&gt;test/helpers.py&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;assert_was_updated&lt;/span&gt;(path, contents):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;assert_was_created&lt;/span&gt;(path):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# and so on&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;use-docstrings-to-describe-tests-scenarios&#34;&gt;Use docstrings to describe tests scenarios&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#use-docstrings-to-describe-tests-scenarios&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is my favorite tip ever: if you are testing something complex, &lt;em&gt;add a human-readable description&lt;/em&gt; of the test inside the docstring.&lt;/p&gt;
&lt;p&gt;Still using our &lt;code&gt;test_can_update_local_file&lt;/code&gt; example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_can_update_local_file&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34; Scenario:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    * Create a file named a.txt in the local folder with
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;      &amp;#34;old&amp;#34; contents
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    * Add a new version of the `a.txt` file in the remote folder
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    * Synchronize the remote and local folders
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    * Check that `a.txt` has been updated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ....
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are two advantages to this approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can be helpful to have a human-readable description of what the test is supposed to be doing when reading the implementation of the code - like any docstring&lt;/li&gt;
&lt;li&gt;Since pytest displays the entire block of the function block that caused the assertion to fail, you get a reminder of what the test was about when reading the failure message.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;reflections-on-the-last-tip&#34;&gt;Reflections on the last tip&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#reflections-on-the-last-tip&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You can stop reading there if you want, but I thought it would be interesting to know how I end up using docstrings in my test code - especially since for a long time, I was convinced that docstrings were useless if the test implementation was clear enough&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;!&lt;/p&gt;
&lt;p&gt;What changed my mind? In two words: &lt;strong&gt;code review&lt;/strong&gt;. let me elaborate.&lt;/p&gt;
&lt;h2 id=&#34;getting-feedback&#34;&gt;Getting feedback&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#getting-feedback&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve had the chance to get my Python test code reviewed by some teammates who did not know pytest very well but were used to frameworks like Mocha or Cucumber. They help me realize this simple truth: using only function names and implementation (in other words, &lt;em&gt;code&lt;/em&gt;) to express all the subtlety of what the tests are about &lt;em&gt;cannot&lt;/em&gt; be enough - kind of obvious when you say it like that, right?&lt;/p&gt;
&lt;p&gt;But in this case code review can only see you &lt;em&gt;what&lt;/em&gt; needs to be improved, but not always &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So I did what I had to: I took a closer look at those other frameworks.&lt;/p&gt;
&lt;h2 id=&#34;getting-to-know-other-frameworks&#34;&gt;Getting to know other frameworks&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#getting-to-know-other-frameworks&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s an implementation of our test using &lt;a href=&#34;https://mochajs.org/&#34;&gt;Mocha&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;describe(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;sync&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  it(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;syncs a remote file&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    remote.addFile(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;a.txt&amp;#39;&lt;/span&gt;, { contents: newContents });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    syncFolders(remote, local);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; actualContents = local.join(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;a.txt&amp;#39;&lt;/span&gt;).readText();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    assert.equal(actualContents, newContents);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here&amp;rsquo;s an implementation using &lt;a href=&#34;https://cucumber.io&#34;&gt;Cucumber&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gherkin&#34; data-lang=&#34;gherkin&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in synchronization.feature - the syntax is called Gherkin&lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;Feature:&lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt; Synchronization
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;Scenario:&lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt; file updated remotely
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;  Given &lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;there is a local file &amp;#39;a.txt&amp;#39; containing &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;old_contents&lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;Given &lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;there is a remote file &amp;#39;a.txt&amp;#39; containing &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;new_contents&lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;When &lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;I synchronize the folders
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;Then &lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;the local file a.txt contains &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;new_contents&lt;/span&gt;&lt;span style=&#34;color:#447fcf&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in synchronization.rb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;Given&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;/there is a local file &amp;#39;{word}&amp;#39; containing &amp;#34;{string}&amp;#34;/&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;do&lt;/span&gt; |path, contents|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;open&lt;/span&gt;(path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;do&lt;/span&gt; |f|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      f.puts contents
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;When&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;/I synchronize the folder/&lt;/span&gt;) &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sync_folders(@local, @remote)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Quite different styles, right?&lt;/p&gt;
&lt;h2 id=&#34;finding-a-middle-ground&#34;&gt;Finding a middle ground&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#finding-a-middle-ground&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;And there you have it: I came up with using docstrings with pytest because it was a nice middle ground between those two approaches.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With Mocha, you write short descriptions in &lt;code&gt;it()&lt;/code&gt; and &lt;code&gt;describe()&lt;/code&gt; and there&amp;rsquo;s no such thing as a &amp;ldquo;test name&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;With Cucumber, you write long and detailed text using the English natural languages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I prefer the docstring solution to the ones above because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;docstrings can be as long as you want (you rarely see descriptions larger than one line in Mocha tests)&lt;/li&gt;
&lt;li&gt;contrary to Cucumber, you are not forced to use any formatting or syntax in your description, and they live right next to the accompanying code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what did we learn?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Being reviewed helps to keep your code readable - but you already knew that, right?&lt;/li&gt;
&lt;li&gt;Exploring new languages and frameworks gives you insights on how to improve your code&lt;/li&gt;
&lt;li&gt;If you are in a team that contains people who use different languages and frameworks than yours and you get them to review your code, it will lead to even better code because you&amp;rsquo;ll be combining the two effects from above!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other terms, consider increasing the diversity of your teams, and don&amp;rsquo;t hesitate to explore new things 😎.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I also believed good code did not need comments - fortunately, I read &lt;a href=&#34;https://hackaday.com/2019/03/05/good-code-documents-itself-and-other-hilarious-jokes-you-shouldnt-tell-yourself&#34;&gt;this article&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>symlinks and .so files on linux - what you need to know</title>
      <link>https://dmerej.info/blog/post/symlinks-and-so-files-on-linux/</link>
      <pubDate>Sat, 18 Apr 2020 14:03:19 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/symlinks-and-so-files-on-linux/</guid>
      <description>&lt;h1 id=&#34;the-issue&#34;&gt;The issue&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-issue&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve seen this happen countless times.&lt;/p&gt;
&lt;p&gt;First, a Linux user asks for help about an error looking like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Error when running `bar`: `libfoo.so.5: no such file or directory`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, someone who&amp;rsquo;s had the same issue suggests creating a symlink from &lt;code&gt;libfoo.so.6&lt;/code&gt; to &lt;code&gt;libfoo.so.5&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And then I come across the dialog some time later and I start crying.&lt;/p&gt;
&lt;p&gt;Why do I cry - it looks like the problem is solved, right?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;code&gt;bar&lt;/code&gt; program seems to run just fine;&lt;/li&gt;
&lt;li&gt;the change was made with just one command (&lt;code&gt;sudo ln&lt;/code&gt;) and can be undone easily (just remove the symlink);&lt;/li&gt;
&lt;li&gt;there was already a symlink from &lt;code&gt;libfoo.so&lt;/code&gt; to &lt;code&gt;libfoo.so.6&lt;/code&gt; anyway!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well, despite the appearances, the problem is &lt;em&gt;not&lt;/em&gt; solved, and doing this
is a &lt;em&gt;terrible idea&lt;/em&gt; in general - like planting a ticking time bomb in the
street you live or shooting yourself in the foot because you&amp;rsquo;ve got a plantar wart.&lt;/p&gt;
&lt;p&gt;But to understand why we need to talk about the language C, shared libraries,
soname bumps, Linux distributions, and package management.&lt;/p&gt;
&lt;p&gt;And because I love telling stories, &lt;em&gt;you&lt;/em&gt;, dear reader, will be the hero
in this one.&lt;/p&gt;
&lt;h1 id=&#34;solving-the-ultimate-question&#34;&gt;Solving the Ultimate Question&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#solving-the-ultimate-question&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s assume a group of people you don&amp;rsquo;t really know (let&amp;rsquo;s called them
&lt;em&gt;The Experts&lt;/em&gt;), wrote a piece of C code than can get the answer to the
Ultimate Question of Life, the Universe, and Everything.&lt;/p&gt;
&lt;p&gt;For obvious reasons, they want to keep the source code private, so here&amp;rsquo;s
what they did:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They wrote a &lt;em&gt;header file&lt;/em&gt; containing the &lt;code&gt;get_answer&lt;/code&gt; declaration named &lt;code&gt;answer.h&lt;/code&gt; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// in answer.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#pragma once
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extern&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;get_answer&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;They created a &lt;em&gt;shared library&lt;/em&gt; called &lt;code&gt;libanswer.so&lt;/code&gt; from their source file (&lt;code&gt;answer.c&lt;/code&gt;
in this case):&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; gcc -shared libanswer.so answer.c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That way, everyone who needs to get the answer to the Ultimate Question of Life, the
Universe, and Everything can buy the &lt;code&gt;libanswer.so&lt;/code&gt; compiled library and the &lt;code&gt;answer.h&lt;/code&gt; header
and call the &lt;code&gt;get_answer()&lt;/code&gt; function - let&amp;rsquo;s see how.&lt;/p&gt;
&lt;h1 id=&#34;using-the-library-from-the-experts&#34;&gt;Using the library from The Experts&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-the-library-from-the-experts&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You&amp;rsquo;ve bought the &lt;code&gt;libanswer.so&lt;/code&gt; and &lt;code&gt;answer.h&lt;/code&gt; files from The Experts
and have put them next to a file you&amp;rsquo;ve wrote named &lt;code&gt;print-answer.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// in print-answer.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;answer.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* answer = &lt;span style=&#34;color:#447fcf&#34;&gt;get_answer&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;The answer is %s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;, answer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You were told that &lt;code&gt;gcc&lt;/code&gt; can compile C code and &lt;em&gt;link against&lt;/em&gt; shared libraries
if you put them on the command line, so you try and run this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; gcc libanswer.so print-answer.c -o print-answer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But it does not work, and you get the following error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;print-answer.c:2:10: fatal error: answer.h: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Wait a minute - the &lt;code&gt;answer.h&lt;/code&gt; file is &lt;em&gt;right there&lt;/em&gt; - what does that mean,
&amp;ldquo;No such file or directory&amp;rdquo;?.&lt;/p&gt;
&lt;p&gt;After a bit of research, you discover that &lt;code&gt;gcc&lt;/code&gt; uses a list of paths called
the &amp;ldquo;include path&amp;rdquo; where it looks for headers. You check on your machine,
and sure enough, &lt;code&gt;/usr/include/&lt;/code&gt; is one of the elements of this list, and &lt;code&gt;stdio.h&lt;/code&gt;
is in &lt;code&gt;/usr/include/stdio.h&lt;/code&gt;, which explains why &lt;code&gt;gcc&lt;/code&gt; did not complain
about the first include.&lt;/p&gt;
&lt;p&gt;To fix the compilation error, you add the &lt;code&gt;-I .&lt;/code&gt; option to the command line
so that current directory is added to the list of include paths:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; gcc -I . libanswer.so print-answer.c -o print-answer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then it compiles.&lt;/p&gt;
&lt;p&gt;Now you try and run the &lt;code&gt;print-answer&lt;/code&gt; program, but you get a new error message:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; ./print-answer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt; error while loading shared libraries: libanswer.so
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt; cannot open shared object file: No such file or directory
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s the same error message as in the introduction and &lt;strong&gt;the operating
system is lying to us&lt;/strong&gt;. The file &lt;code&gt;libanswer.so&lt;/code&gt; is right there!  What&amp;rsquo;s happening there?&lt;/p&gt;
&lt;p&gt;After more investigation, you figure it out:  when you compiled the &lt;code&gt;print-answer&lt;/code&gt;
executable, there was a small piece of binary inside it that recorded the &lt;em&gt;name&lt;/em&gt;
of the &lt;code&gt;.so&lt;/code&gt; file it was linked against. You can check it by running the &lt;code&gt;readelf&lt;/code&gt; command and display
the &lt;em&gt;dynamic section&lt;/em&gt; of your program:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; readelf -d ./print-answer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Dynamic section at offset 0x2de8 contains 27 entries:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;  Tag        Type                         Name/Value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt; 0x0000000000000001 (NEEDED)             Shared library: [libanswer.so]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt; 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a way, the &lt;code&gt;print-answer&lt;/code&gt; program &amp;ldquo;knows&amp;rdquo; that it &lt;em&gt;needs&lt;/em&gt; &lt;code&gt;libanswer.so&lt;/code&gt;
to run. Crucially, it does not know nor cares about where &lt;code&gt;libanswer.so&lt;/code&gt;
really &lt;em&gt;is&lt;/em&gt;. &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Then, when you run &lt;code&gt;./print-answer&lt;/code&gt;, the operating system sees the name of the shared library in the
dynamic section and tries to locate it. Like &lt;code&gt;gcc&lt;/code&gt;, it finds &lt;code&gt;libc.so.6&lt;/code&gt; by itself (in
&lt;code&gt;/usr/lib/libc.so.6&lt;/code&gt; for instance) - but it&amp;rsquo;s unable to find the &lt;code&gt;libanswer.so&lt;/code&gt; shared
library in the current directory.&lt;/p&gt;
&lt;p&gt;Fortunately, you can fix that by using a special environment variable called &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; &lt;span style=&#34;color:#40ffff&#34;&gt;LD_LIBRARY_PATH&lt;/span&gt;=. ./print-answer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;The answer is 42
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time, the operating system looks for &lt;code&gt;libanswer.so&lt;/code&gt; in the current directory, finds it, and
when required, invokes the code for the &lt;code&gt;get_answer()&lt;/code&gt; function from the shared library.&lt;/p&gt;
&lt;p&gt;That gets you thinking - you did not have to do any of this for &lt;code&gt;print-answer&lt;/code&gt; to find the
&lt;code&gt;libc.so&lt;/code&gt; library and the &lt;code&gt;stdio.h&lt;/code&gt; header.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What if it was possible to compile &lt;code&gt;libanswer.so&lt;/code&gt; once and for all?&lt;/li&gt;
&lt;li&gt;And what if there was a way to compile the &lt;code&gt;print-answer.c&lt;/code&gt; source file
without having to copy/paste the header and the shared library, and remember
all the various &lt;code&gt;gcc&lt;/code&gt; options?&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;becoming-a-packager&#34;&gt;Becoming a packager&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#becoming-a-packager&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s assume The Experts realized that their business model was not going
to work and decided to publish their source files for free instead. Yay
open source!&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the contents of their &lt;code&gt;answer.c&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;answer.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt; * &lt;span style=&#34;color:#447fcf&#34;&gt;get_answer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Disappointing, I know
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; r = &lt;span style=&#34;color:#3677a9&#34;&gt;6&lt;/span&gt; * &lt;span style=&#34;color:#3677a9&#34;&gt;7&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt; buf[&lt;span style=&#34;color:#3677a9&#34;&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;snprintf&lt;/span&gt;(buf, &lt;span style=&#34;color:#3677a9&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;%d&amp;#34;&lt;/span&gt;, r);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;strdup&lt;/span&gt;(buf);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since you are an Arch Linux user,  you decide to lookup documentation about the &lt;code&gt;pacman&lt;/code&gt; package manager
and how generate and publish Arch Linux packages &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;After a while, you manage to write a working &lt;code&gt;PGKBUILD&lt;/code&gt; for &lt;code&gt;libanswer&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;pkgname&lt;/span&gt;=libanswer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;pkgver&lt;/span&gt;=1.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;pkgrel&lt;/span&gt;=&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;pkgdesc&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Answer the Ultimate Question&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;arch&lt;/span&gt;=(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;x86_64&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;build() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gcc -I . -shared answer.c -o libanswer.so
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;package ()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mkdir -p &lt;span style=&#34;color:#40ffff&#34;&gt;$pkgdir&lt;/span&gt;/usr/{include,lib}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  install answer.h &lt;span style=&#34;color:#40ffff&#34;&gt;$pkgdir&lt;/span&gt;/usr/include/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  install libanswer.so &lt;span style=&#34;color:#40ffff&#34;&gt;$pkgdir&lt;/span&gt;/usr/lib
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then you build the package with &lt;code&gt;makepkg&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;color:#40ffff&#34;&gt;makepkg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;==&amp;gt; Making package: libanswer 1.0-1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;==&amp;gt; Finished making: libanswer 1.0-1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Everything goes well, and you now have a file named &lt;code&gt;libanswer-1.0-1-x86_64.pkg.tar.xz&lt;/code&gt;
next to your &lt;code&gt;PGKBUILD&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You install the package with &lt;code&gt;pacman&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; sudo pacman -U libanswer-1.0-1-x86_64.pkg.tar.xz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then you find out that you can compile and run &lt;code&gt;print-answer.c&lt;/code&gt; from anywhere
in the system using the following commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ gcc print-answer.c -lanswer -o ./print-answer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ./print-answer
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The answer is &lt;span style=&#34;color:#3677a9&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time you need only the &lt;em&gt;name&lt;/em&gt; of the library (the part without the
&lt;code&gt;lib&lt;/code&gt; prefix and the &lt;code&gt;.so&lt;/code&gt; suffix) after the &lt;code&gt;-l&lt;/code&gt; option. You do &lt;em&gt;not&lt;/em&gt;
have to worry about include paths or use the &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; environment
variable -  neat!&lt;/p&gt;
&lt;p&gt;What you&amp;rsquo;ve accomplished is called &lt;em&gt;packaging the &lt;code&gt;answer&lt;/code&gt; library&lt;/em&gt;, and it&amp;rsquo;s
what  &lt;em&gt;package maintainers&lt;/em&gt; do - well done.&lt;/p&gt;
&lt;p&gt;Impressed by your packaging skills&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;, the Arch Linux maintainers allow
you to publish your package in official repositories, which means
everyone using Arch Linux is now able to install the &lt;code&gt;libanswer&lt;/code&gt; package in
just one command!&lt;/p&gt;
&lt;h1 id=&#34;a-simple-change&#34;&gt;A simple change&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-simple-change&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A few days later, The Experts release a new version of their library (1.1), containing a nice optimization:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;get_answer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;strdup&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;42&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since you are the maintainer of the &lt;code&gt;libanswer&lt;/code&gt; package, you quickly update
the PKGBUILD and publish a new release.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-pkgver=1.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+pkgver=1.1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt; pkgrel=1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; pkgdesc=&amp;#34;Answers the Ultimate Question&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; arch=(&amp;#39;x86_64&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; source=(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You build and install the package on your machine and check it still works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; makepkg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; sudo pacman -U libanswer-1.1-1-x86_64.pkg.tar.xz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then you publish the new version of the &lt;code&gt;libanswer&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where Linux distributions really shine (and the whole reason we use
shared libraries in the first place).  Once the new package is published,
&lt;em&gt;any&lt;/em&gt; Arch Linux user who installs it will get the latest version
of &lt;code&gt;libanswer.so&lt;/code&gt; in their system, and all the programs that were linked
against it will use the latest version - this is especially important if the
new version contains a security bug fix for instance.&lt;/p&gt;
&lt;h1 id=&#34;another-change&#34;&gt;Another change&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#another-change&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A week later, The Experts realize they don&amp;rsquo;t really need to return a string
from the &lt;code&gt; get_answer()&lt;/code&gt;  function, and that a simple &lt;code&gt;int&lt;/code&gt; would suffice.&lt;/p&gt;
&lt;p&gt;So they modify both their header and source files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- char* get_answer();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ int get_answer();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;answer.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_answer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;42&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And they publish a release note:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-md&#34; data-lang=&#34;md&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;font-weight:bold&#34;&gt;# The answer project
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;text-decoration:underline&#34;&gt;## Version 2.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;text-decoration:underline&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;*&lt;/span&gt; Change the return type of the &lt;span style=&#34;color:#ed9d13&#34;&gt;`get_answer()`&lt;/span&gt; function from &lt;span style=&#34;color:#ed9d13&#34;&gt;`char*`&lt;/span&gt; to &lt;span style=&#34;color:#ed9d13&#34;&gt;`int`&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;text-decoration:underline&#34;&gt;## Version 1.1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;text-decoration:underline&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;*&lt;/span&gt; This release implements performance optimizations.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;text-decoration:underline&#34;&gt;## Version 1.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;text-decoration:underline&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;*&lt;/span&gt; First public release!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Upon hearing the good news, you download the latest sources of the project,
and you modify your &lt;code&gt;print-answer.c&lt;/code&gt; source file to use the latest version
of the library:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;answer.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; answer = &lt;span style=&#34;color:#447fcf&#34;&gt;get_answer&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;The answer is %d&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;, answer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You compile everything and check the code still works:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ gcc -I . -shared answer.c -o libanswer.so
$ gcc -I . libanswer.so print-answer.c -o ./print-answer
$ LD_LIBRARY_PATH=. ./print-answer
The answer is 42
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Time to publish the v2!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-pkgver=1.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+pkgver=2.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt; pkgrel=1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; pkgdesc=&amp;#34;Answers the Ultimate Question&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; arch=(&amp;#39;x86_64&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; source=(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; makepkg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; sudo pacman -U libanswer-2.0-1-x86_64.pkg.tar.xz
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Easy as pie - satisfied, you publish the new package and go to bed.&lt;/p&gt;
&lt;h1 id=&#34;when-shit-hits-the-fan&#34;&gt;When shit hits the fan&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#when-shit-hits-the-fan&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The next morning you receive the following e-mail:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Subject : latest libanswer package update broke display-answer-pp program

Hello,

I&amp;#39;m using `display-answer-pp` version 0.4, and when I updated `libanswer` to
the version 2.0, I got the following error:

./display-answer-pp
zsh: segmentation fault (core dumped)  ./display-answer-pp

Downgrading the `libanswer` package fixes the problem. Please advise.

Signed: Bob
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Welcome to the joys of packaging!&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve never heard of the &lt;code&gt;display-answer-pp&lt;/code&gt; package - what is going on?&lt;/p&gt;
&lt;p&gt;After a bit of research, you find out that someone wrote a &lt;code&gt;display-answer-pp&lt;/code&gt;
program using your &lt;code&gt;libanswer&lt;/code&gt; package and published it on the official Arch Linux
repositories a few days ago.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the code for &lt;code&gt;display-answer-pp&lt;/code&gt; looks like - it&amp;rsquo;s a single &lt;code&gt;C++&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;answer.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; answer = get_answer();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std::cout &amp;lt;&amp;lt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;The answer is: &amp;#34;&lt;/span&gt; &amp;lt;&amp;lt; answer &amp;lt;&amp;lt; std::endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So what happened?&lt;/p&gt;
&lt;p&gt;Well, the problem is that you forgot to coordinate with your fellow packagers!&lt;/p&gt;
&lt;p&gt;You see, when &lt;code&gt;display-answer-pp&lt;/code&gt; was being packaged, the &lt;code&gt;get_answer()&lt;/code&gt;
function was returning a &lt;code&gt;char*&lt;/code&gt;. When you published &lt;code&gt;answer&lt;/code&gt; version 2.0,
the code for the function &lt;code&gt;get_answer()&lt;/code&gt; started returning an
&lt;code&gt;int&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;So when Bob updated &lt;code&gt;libanswer&lt;/code&gt; after having installed &lt;code&gt;display-answer-pp&lt;/code&gt;,
and tried to re-run the program, all hell break loose, because the compiled
C++ code expected a &lt;em&gt;pointer&lt;/em&gt; to a string and got an &lt;em&gt;int&lt;/em&gt; instead.&lt;/p&gt;
&lt;p&gt;In other terms, the &lt;em&gt;application &lt;em&gt;binary&lt;/em&gt; interface&lt;/em&gt; (or ABI for short) of the &lt;code&gt;libanswer&lt;/code&gt; library broke.&lt;/p&gt;
&lt;h1 id=&#34;you-break-it-you-fix-it&#34;&gt;You break it, you fix it&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#you-break-it-you-fix-it&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Unfortunately, there&amp;rsquo;s only one way to fix an ABI breakage: you need to
&lt;em&gt;recompile&lt;/em&gt; everything that was linked against the old version of the library.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s one of the main issues package maintainers have to solve. They need two very different features when it comes
to libraries updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If the new version of the library is ABI-compatible with the previous one, end-users should be able to get it
by simply updating &lt;em&gt;the one package&lt;/em&gt; that contains it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If not, they need to make sure &lt;em&gt;none of the programs that depend on the library&lt;/em&gt; break when the update is made.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-arch-way&#34;&gt;The Arch Way&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-arch-way&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s how Arch maintainers solve this problem. In our example, they would have published &lt;code&gt;libanswer&lt;/code&gt; v2
in a special repository named &amp;ldquo;staging&amp;rdquo;. Then, they would have rebuild every package that depends
on &lt;code&gt;libanswer&lt;/code&gt; (so both &lt;code&gt;print-answer&lt;/code&gt; and &lt;code&gt;display-answer-pp&lt;/code&gt;) and pushed those to the staging repository.&lt;/p&gt;
&lt;p&gt;Finally, after a period of testing, they would have moved &lt;code&gt;libanswer&lt;/code&gt;, &lt;code&gt;print-answer&lt;/code&gt; and &lt;code&gt;display-answer-pp&lt;/code&gt;
in the official repositories in one swift update. They would have used a &lt;em&gt;to do list&lt;/em&gt; like
&lt;a href=&#34;https://www.archlinux.org/todo/hdf5-1120-release/&#34;&gt;this one&lt;/a&gt; to coordinate the packaging tasks.&lt;/p&gt;
&lt;p&gt;This means that if you try and update &lt;code&gt;libanswer&lt;/code&gt; without upgrading &lt;em&gt;every
other package&lt;/em&gt; that depends on it, you risk breaking your installation -
and that&amp;rsquo;s why partial updates are not supported on Arch Linux.&lt;/p&gt;
&lt;h2 id=&#34;the-debian-way&#34;&gt;The Debian Way&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-debian-way&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Debian maintainers use another strategy. When they package a library,
they include its version number in the name of the package. What&amp;rsquo;s more,
they have a separate &lt;em&gt;development&lt;/em&gt; package that contains the files required for
compiling programs that use the library. They also use a compilation trick
called the &lt;code&gt;soname&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how this works.&lt;/p&gt;
&lt;p&gt;First, they tell &lt;code&gt;gcc&lt;/code&gt; to use the correct soname option when linking the library &lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; gcc -I . answer.c -shared -Wl,-soname=libanswer.so.1 -o libanswer.so.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;They use the outcome of the build to generate two packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;libanswer-dev&lt;/code&gt;, that contains a symlink &lt;code&gt;libanswer.so -&amp;gt; libanswer.so.1&lt;/code&gt; and the &lt;code&gt;answer.h&lt;/code&gt; header&lt;/li&gt;
&lt;li&gt;and &lt;code&gt;libanswer1&lt;/code&gt;, that contains &lt;strong&gt;only&lt;/strong&gt; the &lt;code&gt;libanswer.so.1&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, they build &lt;code&gt;display-answer-pp&lt;/code&gt; for the first time, using the &lt;code&gt;libanswer-dev&lt;/code&gt; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; g++ -lanswer display-answer.cpp -o ./display-answer-pp
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because &lt;code&gt;libanswer.so&lt;/code&gt; was built with the &lt;code&gt;-soname=libanswer.so.1&lt;/code&gt; option, the &lt;code&gt;display-answer-pp&lt;/code&gt; binary
now &lt;em&gt;knows&lt;/em&gt; that it needs &lt;code&gt;libanswer.so.1&lt;/code&gt; at runtime:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; readelf -d display-answer-pp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Tag                  Type               Name/value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;0x0000000000000001 (NEEDED)             Shared library: [libanswer.so.1]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When the v2 version of &lt;code&gt;libanswer&lt;/code&gt; is published by The Experts, they rebuild
the shared library with an appropriate soname:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; gcc -I . answer.c -shared -Wl,-soname=libanswer.so.2 -o libanswer.so.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;They use the outcome of the build to &lt;em&gt;update&lt;/em&gt; the &lt;code&gt;libanswer-dev&lt;/code&gt; package and to create
a &lt;em&gt;brand new&lt;/em&gt; &lt;code&gt;libanswer2&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;At this point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;libanswer-dev&lt;/code&gt; contains a symlink &lt;code&gt;libanswer.so -&amp;gt; libanswer.so.2&lt;/code&gt; and the updated &lt;code&gt;answer.h&lt;/code&gt; header&lt;/li&gt;
&lt;li&gt;&lt;code&gt;libanswer2&lt;/code&gt; contains only the &lt;code&gt;libanswer.so.2&lt;/code&gt; file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, they build &lt;code&gt;display-answer-pp&lt;/code&gt; for the second time, using the updated &lt;code&gt;libanswer-dev&lt;/code&gt; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; g++ -lanswer display-answer.cpp -o ./display-answer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time, &lt;code&gt;display-answer-pp&lt;/code&gt; knows that it needs &lt;code&gt;libanswer.so.2&lt;/code&gt; at runtime:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; readelf -d display-answer-pp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Tag                  Type               Name/value
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;0x0000000000000001 (NEEDED)             Shared library: [libanswer.so.2]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s sum up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Both &lt;code&gt;libanswer1&lt;/code&gt; and &lt;code&gt;libanswer2&lt;/code&gt; packages can co-exist in the same system,
since they contain different filenames&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;libanswer-dev&lt;/code&gt; package does not need to be installed for
&lt;code&gt;display-answer-pp&lt;/code&gt; to run since the program contain the versioned soname
in its dynamic section&lt;/li&gt;
&lt;li&gt;If you want to rebuild a program when a new version of the library is out,
you just install the latest &lt;code&gt;libanswer-dev&lt;/code&gt; package - the command used for
compilation does not have to change at all!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Clever, right?&lt;/p&gt;
&lt;p&gt;Because of this technique, the update from &lt;code&gt;libanswer&lt;/code&gt; v1 to &lt;code&gt;libanswer&lt;/code&gt;
v2 is often called &lt;em&gt;a soname bump&lt;/em&gt; - the update from &lt;code&gt;v1&lt;/code&gt; to &lt;code&gt;v1.1&lt;/code&gt; is just
a regular update.&lt;/p&gt;
&lt;p&gt;Quite often, a backward incompatible update correspond to the first digit
of the soname to be updated. &lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now you know - different versions of a library have various sonames, and
the symlinks are carefully crafted by distribution maintainers.&lt;/p&gt;
&lt;p&gt;So, when you create a symlink yourself, you are taking a huge risk, especially
when creating links between libraries that have a different leading digit in
their soname!&lt;/p&gt;
&lt;p&gt;As we saw, using the incorrect library at runtime can cause crashes, and if
you break an essential binary (like &lt;code&gt;bash&lt;/code&gt; for instance), you may no longer
be able to log in, which means your only choice may be to re-install your whole system
from scratch. This is not theoretical by the way: it happened to me &lt;em&gt;years ago&lt;/em&gt;,
and I still remember it to this day.&lt;/p&gt;
&lt;p&gt;So, what to do if you get this error?&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Error when running `bar`: `libfoo.so.5: no such file or directory`
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;bar&lt;/code&gt; comes from a package on your distribution, update all packages
and then open a bug report if the problem persists&lt;/li&gt;
&lt;li&gt;If not, try and re-compile &lt;code&gt;bar&lt;/code&gt; - possibly after updating the &lt;code&gt;libfoo-dev&lt;/code&gt; package.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But &lt;em&gt;please&lt;/em&gt;, &lt;em&gt;please&lt;/em&gt; do not create a symlink from &lt;code&gt;libfoo.so.6&lt;/code&gt; to
&lt;code&gt;libfoo.so.5&lt;/code&gt; or suggest this solution to someone else.  Together, let&amp;rsquo;s
put an end to this bad, bad, advice. Thank you!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;If you&amp;rsquo;re puzzled by the &lt;code&gt;__cplusplus&lt;/code&gt; stuff don&amp;rsquo;t worry - it&amp;rsquo;s just so that the answer library
is usable from C++ too.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;By the way, it needs &lt;code&gt;libc.so&lt;/code&gt; because the compiled code for &lt;code&gt;printf&lt;/code&gt; lives there.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;You&amp;rsquo;re using Arch Linux because you&amp;rsquo;re cool and you want to learn - good for you!&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Reminder: it&amp;rsquo;s a story I made up!&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;Actually, this is often done automatically by whatever build system the library is using&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;
&lt;p&gt;Sadly it&amp;rsquo;s not always the case: &lt;code&gt;lua&lt;/code&gt; and &lt;code&gt;libpng&lt;/code&gt; are notable exceptions.&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Classes Rock</title>
      <link>https://dmerej.info/blog/post/classes-rock/</link>
      <pubDate>Sat, 16 Nov 2019 19:26:27 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/classes-rock/</guid>
      <description>&lt;p&gt;This is the second article in a 2-part series of blog posts that examine
the complicated relationships between the real world and object-oriented
code. If you haven&amp;rsquo;t already, you should read the first part:
&lt;a href=&#34;https://dmerej.info/blog/post/classes-suck/&#34;&gt;classes suck&lt;/a&gt; first.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s recap: we used a &lt;code&gt;Robot&lt;/code&gt; class to implement the
client specifications. It worked well, until we tried to model the
&lt;code&gt;start&lt;/code&gt; and &lt;code&gt;stop&lt;/code&gt; methods with a mutable state. We concluded that
blindly using classes (with methods and mutable attributes)
to represent real-worlds objects was a mistake.&lt;/p&gt;
&lt;h1 id=&#34;taking-a-second-look-at-the-code&#34;&gt;Taking a second look at the code&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#taking-a-second-look-at-the-code&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s look at the code again (minus the &lt;code&gt;stop&lt;/code&gt; method),
along with the spec:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;When robots come off the factory floor, they have no name:&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;The first time you boot them up, a random name is generated:&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self._name &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = generate_name()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;When a robot is reset, its name gets wiped:&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;reset&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So we &lt;em&gt;were&lt;/em&gt; modeling real-world objects with our class after all: the mistake
we made was trying to model the &lt;em&gt;robot&lt;/em&gt;. But using code to model &lt;em&gt;the specification&lt;/em&gt;
worked!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re not convinced, consider this: the &lt;code&gt;stop()&lt;/code&gt; method is
empty because the specification said &lt;em&gt;nothing&lt;/em&gt; about what happens when the robot is
stopped.&lt;/p&gt;
&lt;p&gt;If the specification said something like &lt;em&gt;the robot cannot be reset when it is
started&lt;/em&gt;, then using a &lt;code&gt;stopped&lt;/code&gt; attribute may have been a good idea.&lt;/p&gt;
&lt;h1 id=&#34;encapsulation&#34;&gt;Encapsulation&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#encapsulation&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So far we talked only about methods and attributes. There&amp;rsquo;s another aspect of
programming with classes I&amp;rsquo;d like to examine next: the concept of
&lt;em&gt;encapsulation&lt;/em&gt;, or how to separate &amp;ldquo;private&amp;rdquo; implementation and &amp;ldquo;public&amp;rdquo;
interface.&lt;/p&gt;
&lt;p&gt;Basically, there are some details of a class that matter
to the people who &lt;em&gt;wrote&lt;/em&gt; the class but that &lt;em&gt;users&lt;/em&gt; of said class should not know about.&lt;/p&gt;
&lt;p&gt;What does this have to do with the real world? &lt;strong&gt;Everything!&lt;/strong&gt; Let me show you.&lt;/p&gt;
&lt;h2 id=&#34;a-single-line-telling-a-whole-story&#34;&gt;A single line telling a whole story&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-single-line-telling-a-whole-story&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In Python, to signify to users of a class that an attribute is not part
of the &amp;ldquo;public&amp;rdquo; interface, you prefix it with an underscore, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By the way, there are already two pieces of information here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;robot names are empty at first&lt;/li&gt;
&lt;li&gt;the name likely changes over time (otherwise it would probably have been
passed as a parameter in the constructor)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But that&amp;rsquo;s again about the specification. What does it mean to have &lt;code&gt;_name&lt;/code&gt; as a private attribute?&lt;/p&gt;
&lt;h2 id=&#34;working-in-teams&#34;&gt;Working in teams&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#working-in-teams&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s imagine we are writing software inside a big company with several
teams. Reading the specification again, it&amp;rsquo;s clear that the client is
&lt;em&gt;extremely&lt;/em&gt; worried about robot names: each and every line of the specification
talks about it! If there is a bug affecting the robot name, the client is
going to get pissed.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s where using &lt;em&gt;encapsulation&lt;/em&gt; makes sense: by &amp;ldquo;hiding&amp;rdquo; the &lt;code&gt;name&lt;/code&gt; attribute from the users of the Robot class,
we are actually covering our bases. If someone from another team writes &lt;code&gt;robot._name = &amp;quot;something-else&amp;quot;&lt;/code&gt;,
the client will get mad (the robot name no longer has the correct format), but we can  tell him it&amp;rsquo;s not our fault:
the other team should not have broken the encapsulation without asking us first!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So, which is it? Do classes rock or suck at modeling the real world?&lt;/p&gt;
&lt;p&gt;Well, it all depends on what you mean by &amp;ldquo;the real world&amp;rdquo;. My advice to you is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clarify specifications as much as possible&lt;/li&gt;
&lt;li&gt;write code that closely resembles the specification&lt;/li&gt;
&lt;li&gt;use encapsulation when necessary to protect yourself against misuses of your code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When used correctly, classes are a great way to accomplish all of the above, but
they are also easy to misuse.&lt;/p&gt;
&lt;p&gt;Finally, let&amp;rsquo;s go back to our original question: &amp;ldquo;is modeling the real world
in code worth it?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Well, if it allows you to implement the specifications correctly and makes
things easier for you and your teammates, then yes, it&amp;rsquo;s definitely worth it.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s hard, but trying and solve this challenge is what I love about programming.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update 2021-09-16: see also this fantastic article by By Mathias Verraes and Rebecca Wirfs-Brock:
called &lt;a href=&#34;https://verraes.net/2021/09/design-and-reality/&#34;&gt;Design and Reality&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Classes Suck</title>
      <link>https://dmerej.info/blog/post/classes-suck/</link>
      <pubDate>Sat, 09 Nov 2019 19:06:44 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/classes-suck/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A long time ago I received a lecture about the usage of databases and software design. More specifically, how to translate relationships like &amp;ldquo;one-to-one&amp;rdquo;, &amp;ldquo;many-to-many&amp;rdquo;, or &amp;ldquo;one-to-many&amp;rdquo; inside databases schemas.&lt;/p&gt;
&lt;p&gt;Ten years later, I still remember one thing the teacher said at the beginning of the course:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you are designing your database schema, your enemy is the real world. The real world is &lt;em&gt;always&lt;/em&gt; more complicated than you anticipated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is not new, of course, but it raises some interesting questions: how can we model the real world in our code? Is it worth it? Is not all software made of abstract objects? Are classes and instances the correct way to do it?&lt;/p&gt;
&lt;h1 id=&#34;a-two-part-exploration&#34;&gt;A two-part exploration&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-two-part-exploration&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;In these two parts series, we&amp;rsquo;ll try and answer the last question.&lt;/p&gt;
&lt;p&gt;We will use an exercise I&amp;rsquo;ve stolen from the &lt;a href=&#34;https://exercism.io/&#34;&gt;exercism.io&lt;/a&gt; website, and the two parts will argue opposing points of view.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with part one: &lt;em&gt;classes suck&lt;/em&gt;. Bear in mind there we&amp;rsquo;ll be a part two called &lt;em&gt;classes rock&lt;/em&gt;, so don&amp;rsquo;t leave angry comments below just yet :)&lt;/p&gt;
&lt;p&gt;One last thing: this is a story based on real events: the code I&amp;rsquo;m about to show below was written this way by students I&amp;rsquo;ve just taught about instances and classes in Python.&lt;/p&gt;
&lt;h1 id=&#34;the-robot-factory-exercise&#34;&gt;The Robot factory exercise&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-robot-factory-exercise&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here are the specifications of the exercise:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Your are a developer inside a robot factory. Your task is to manage robot settings. Here are the rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When robots come off the factory floor, they have no name.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The first time you boot them up, a random name is generated in the format
of two uppercase letters followed by three digits, such as RX837 or BC811.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Every once in a while we need to reset a robot to its factory settings,
which means that their name gets wiped. The next time you ask, it will
respond with a new random name.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;And here&amp;rsquo;s the code we&amp;rsquo;re given a starting point:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Put your code here:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_name_is_not_set_at_first&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot = Robot()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; robot.name() &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_started_robots_have_a_name&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot = Robot()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.start()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    actual_name = robot.name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; re.&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;r&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;^[A-Z]&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{2}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\d&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{3}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;$&amp;#34;&lt;/span&gt;, actual_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_name_does_not_change_when_rebooted&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot = Robot()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.start()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name1 = robot.name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.stop()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.start()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name2 = robot.name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; name1 == name2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_name_changes_after_a_reset&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot = Robot()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.start()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name1 = robot.name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.stop()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.reset()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    robot.start()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name2 = robot.name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; name1 != name2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try to fix tests one by one, starting with the first one.&lt;/p&gt;
&lt;h1 id=&#34;making-the-first-tests-pass&#34;&gt;Making the first tests pass&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#making-the-first-tests-pass&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;All we need is a &lt;code&gt;name()&lt;/code&gt; method that returns &lt;code&gt;None&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For the next test, we need a &lt;code&gt;start&lt;/code&gt; method that will cause the name to change. Let&amp;rsquo;s store the name in a private attribute &lt;code&gt;_name&lt;/code&gt; and adapt the rest of the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;generate_name&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# implementation omitted for brevity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self._name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = generate_name()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To fix the next test, we need to implement &lt;code&gt;stop&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;generate_name&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self._name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = generate_name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;stop&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then we get:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;test_name_does_not_change_when_rebooted:
&amp;gt;       assert name1 == name2
E       AssertionError: assert &amp;#39;KJ721&amp;#39; == &amp;#39;JO813&amp;#39;
E         - KJ721
E         + JO813
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;making-the-test-about-reboot-pass---first-attempt&#34;&gt;Making the test about reboot pass - first attempt&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#making-the-test-about-reboot-pass---first-attempt&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Clearly, we have a bug in our implementation. The robot&amp;rsquo;s name must not change when it&amp;rsquo;s rebooted.&lt;/p&gt;
&lt;p&gt;If we follow the &amp;ldquo;code objects must reflect real-world objects&amp;rdquo; rule, we may be tempted to say that robots have a &lt;em&gt;state&lt;/em&gt; and that this state can be used to know when the name must be regenerated.&lt;/p&gt;
&lt;p&gt;And we can choose to represent the state of the robot with a &lt;code&gt;stopped&lt;/code&gt; attribute inside the &lt;code&gt;Robot&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Better make sure robots are stopped when&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# they come out of the factory floor :)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.stopped =  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self._name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = generate_name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.stopped = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;stop&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.stopped = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s where classes have failed us. This &lt;code&gt;stopped&lt;/code&gt; attribute does not help &lt;em&gt;at all&lt;/em&gt; making the test pass.&lt;/p&gt;
&lt;p&gt;We tried and model the real world in our class but it was useless. And then we realize that there&amp;rsquo;s no so such thing as a &amp;ldquo;boolean&amp;rdquo; in the real world. In the real world, robots have LEDs that are turned on or turned off!&lt;/p&gt;
&lt;h1 id=&#34;making-the-test-about-reboot-pass---second-try&#34;&gt;Making the test about reboot pass - second try&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#making-the-test-about-reboot-pass---second-try&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s revert the change that introduced the &lt;code&gt;stopped&lt;/code&gt; attribute, and look at the implementation again. It becomes clear that to make the test pass, we just need an if in the &lt;code&gt;start&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self._name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self._name &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;            self._name = generate_name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;stop&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Making the last test pass is easy: we only need to reset the &lt;code&gt;._name&lt;/code&gt; attribute when the robot is reset:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Robot&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;name&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self._name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;start&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self._name &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self._name = generate_name()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;stop&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;reset&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now all test pass and we&amp;rsquo;re done.&lt;/p&gt;
&lt;h1 id=&#34;temporary-conclusion&#34;&gt;(Temporary) conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#temporary-conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Looking at the code, it looks like our object has nothing to do with the real world. The closest connection with the real world is the &lt;code&gt;._name&lt;/code&gt; attribute which is probably just a bunch of zeros and ones inside the memory chip of the robot.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s face it, using classes to represent the real world is a myth, probably spread by overzealous Java developers, or clueless researchers locked inside their ivory towers.&lt;/p&gt;
&lt;p&gt;Or is it? Let&amp;rsquo;s find out in &lt;a href=&#34;https://dmerej.info/blog/post/classes-rock/&#34;&gt;part two&lt;/a&gt;!.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I am a rusty frog</title>
      <link>https://dmerej.info/blog/post/i-am-a-rusty-frog/</link>
      <pubDate>Sat, 27 Jul 2019 09:46:51 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/i-am-a-rusty-frog/</guid>
      <description>&lt;p&gt;Do you know the fable of the frog and the boiling water? It goes like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you drop a frog in a pot of boiling water, it will of course frantically try to clamber out. But if you place it gently in a pot of tepid water and turn the heat on low, it will float there quite placidly. As the water gradually heats up, the frog will sink into a tranquil stupor, exactly like one of us in a hot bath, and before long, with a smile on its face, it will unresistingly allow itself to be boiled to death.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At least that&amp;rsquo;s how Daniel Quinn&amp;rsquo;s tells it in &lt;em&gt;The Story of B&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It is a powerful metaphor, although if you read the &lt;a href=&#34;https://en.wikipedia.org/wiki/Boiling_frog&#34;&gt;Wikipedia article&lt;/a&gt;, it turns out frogs do not actually behave that way.&lt;/p&gt;
&lt;p&gt;But I think there&amp;rsquo;s still some truth it in: if you experience some increasing pain gradually enough, you may not realizing how much you are actually suffering until it&amp;rsquo;s too late. At least it&amp;rsquo;s what happened to me.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start at the beginning, before we start talking about Rust, refactoring, performance bugs and the weaknesses of the human mind.&lt;/p&gt;
&lt;h1 id=&#34;part-1-the-setup&#34;&gt;Part 1: The setup&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#part-1-the-setup&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A long time ago, I realized I spent far too much time typing &lt;code&gt;cd&lt;/code&gt; to navigate between project directories, and that the default &lt;code&gt;ctrl-r&lt;/code&gt; binding for &lt;code&gt;zsh&lt;/code&gt; was a bit awkward to use for me.&lt;/p&gt;
&lt;p&gt;Then I realized I could solve both of those problems by writing two very similar commands: &lt;code&gt;cwd-history&lt;/code&gt; and &lt;code&gt;cmd-history&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk about the former. It&amp;rsquo;s a command-line tool that takes two actions, &lt;code&gt;add&lt;/code&gt;  and &lt;code&gt;list&lt;/code&gt;. Here&amp;rsquo;s how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cmd-history add&lt;/code&gt; takes one parameter and adds it to a &amp;ldquo;database&amp;rdquo; in &lt;code&gt;~/.local/share/bwataout/commands-history&lt;/code&gt;. The database is just a file with one command per line.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cmd-history list&lt;/code&gt; simply dumps the contents of the database to &lt;code&gt;stdout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then,  there&amp;rsquo;s a &lt;code&gt;zsh&lt;/code&gt; hook to run right after a command has been read and is about to be executed. In the hook, &lt;code&gt;cmd-history add&lt;/code&gt; is called with the text of the last command.&lt;/li&gt;
&lt;li&gt;Finally, &lt;code&gt;zsh&lt;/code&gt; is configured so that when &lt;code&gt;ctrl-r&lt;/code&gt; is pressed, the output of &lt;code&gt;cmd-history list&lt;/code&gt; is piped through &lt;code&gt;fzf&lt;/code&gt; and then the selected command is run.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I use a similar program called &lt;code&gt;cwd-history&lt;/code&gt; that does exactly the same thing but for the working directories. It runs in another zsh hook called &lt;code&gt;chpwd&lt;/code&gt;, and is triggered by typing the command &lt;code&gt;z&lt;/code&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;There are a few specifics like making sure the entries are not duplicated or ensuring that every symlink in the added path is resolved, but we&amp;rsquo;ll get to that later.&lt;/p&gt;
&lt;h1 id=&#34;part-2-rir&#34;&gt;Part 2: RIR&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#part-2-rir&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The two programs were written in Python and shared a ton of functionality but since I am a lazy programmer I did not bother with refactoring the code.&lt;/p&gt;
&lt;p&gt;But something was bugging me. There was a small noticeable delay whenever I was using them, particularly on old hardware. So I decided to try and rewrite them in Rust. And surely when I measured the performance, there was a &lt;em&gt;huge&lt;/em&gt; difference in the startup time: Rust compiles directly to machine code, and there was no need to wait for the Python interpreter to start. I was happy.&lt;/p&gt;
&lt;h1 id=&#34;part-3-the-switch-to-kakoune&#34;&gt;Part 3: the switch to Kakoune&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#part-3-the-switch-to-kakoune&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A few months ago, I switched from Neovim to &lt;a href=&#34;https://kakoune.org/&#34;&gt;Kakoune&lt;/a&gt; for my main text editor and was faced with a problem.&lt;/p&gt;
&lt;p&gt;Kakoune does not have any persisting state by design, and I was missing a particular vim feature that allowed me to quickly select any recently opened file (aka. &lt;abbr title=&#34;Most Recently Used&#34;&gt;MRU&lt;/abbr&gt; files).&lt;/p&gt;
&lt;p&gt;But I already knew how to solve that! I wrote yet another tool called &lt;code&gt;mru-files&lt;/code&gt; for reading and writing the MRU files in another database, and write a bit of Kakoune script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Call `mru-files add` with the buffer name when opening a new buffer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hook global BufOpenFile .* %{ nop %sh{ mru-files add  &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;kak_hook_param&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt; } }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Call `mru files list` when pressing &amp;lt;leader key&amp;gt;o:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;map global user o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -docstring &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;open old files&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;: evaluate-commands %sh{ mru-files list --kakoune }&amp;lt;ret&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the &lt;code&gt;--kakoune&lt;/code&gt; option when calling &lt;code&gt;mru-files list&lt;/code&gt;: we need to call the &lt;code&gt;menu&lt;/code&gt; command so that we can present the list of MRU files to the user and open the file when it&amp;rsquo;s selected.&lt;/p&gt;
&lt;p&gt;It looks like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;menu
  &amp;#34;/foo.txt&amp;#34; &amp;#34;edit -existing &amp;#39;foo.txt:&amp;#39;&amp;#34;
  &amp;#34;/bar.txt&amp;#34; &amp;#34;edit -existing &amp;#39;bar.txt&amp;#39;&amp;#34;
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;While I was it, I also added a &lt;code&gt;--kakoune&lt;/code&gt; argument to &lt;code&gt;cwd-history list&lt;/code&gt; so that I could switch to previously visited directories directly from Kakoune:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; map global &lt;span style=&#34;color:#24909d&#34;&gt;cd&lt;/span&gt; o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   -docstring &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;open old working directory&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;: evaluate-commands %sh{ cwd-history list --kakoune }&amp;lt;ret&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;part-4-the-refactoring&#34;&gt;Part 4: the refactoring&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#part-4-the-refactoring&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So now I was faced with &lt;em&gt;three&lt;/em&gt; very similar code written in Rust. It was time for a refactoring &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what I did:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, I added a trait called &lt;code&gt;EntryCollection&lt;/code&gt; that contained methods named &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;list&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;trait&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;list&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;The trait was implemented by three structs: &lt;code&gt;Commands&lt;/code&gt;, &lt;code&gt;WorkingDirs&lt;/code&gt; and &lt;code&gt;MruFiles&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Commands&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Commands&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Deduplicate the entry and store it in self.entries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;list&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// return self.entries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;WorkingDirs&lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;WorkingDirs&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;         &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Convert the entry to a path, check  if it exists,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;         &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// then canonicalize it and insert it in self.entries
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(and similar code for MruFiles)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I wrote a &lt;code&gt;Storage&lt;/code&gt; struct to interact with the database:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries_collection: &lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;&amp;lt;EntriesCollection&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;path: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;std&lt;/span&gt;::path::PathBuf,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Storage&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;db_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;path.join(entries_collection.name());&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;read_db(&amp;amp;db_path);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;entries_collection.add(&amp;amp;entry);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;db_path,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;entries_collection,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;list&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&amp;amp;self.entries_collection.list()&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.entries_collection.add(&amp;amp;entry);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;write_db(&amp;amp;self.db_path,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;self.list())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;I wrote &lt;code&gt;StorageManager&lt;/code&gt; struct to instantiate the &lt;code&gt;Storage&lt;/code&gt; struct with the correct &lt;code&gt;EntriesCollection&lt;/code&gt; implementation depending on a &lt;code&gt;StorageType&lt;/code&gt; enum:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;StorageType&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;CwdHistory,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;CommandsHistory,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;FilesHistory,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;StorageManager&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;   &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;StorageManager&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(storage_type: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;StorageType&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Self&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;&amp;lt;EntriesCollection&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;storage_type&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;StorageType::CwdHistory&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;::new(WorkingDirs::new()),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;StorageType::CommandsHistory&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;::new(Commands::new()),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;StorageType::FilesHistory&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;::new(MruFiles::new()),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Storage::new(entries,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;app_dir);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;StorageManager&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;list&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Delegates to self.storage.list()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Delegates to self.storage.add()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;And finally, I wrote three &lt;code&gt;main&lt;/code&gt; functions that called the &lt;code&gt;StorageManager&lt;/code&gt; constructor, passing it the enum variant.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// In src/bin/cmd-history.rs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bwataout::StorageType;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;bwataout::run_storage_manager(StorageType::CommandsHistory)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// In src/bin/cwd-history.rs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bwataout::StorageType;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;bwataout::run_storage_manager(StorageType::CwdHistory)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// In src/bin/mru-files.rs.rs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bwataout::StorageType;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;bwataout::run_storage_manager(StorageType::FilesHistory)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that was my first mistake: I forgot to measure performance &lt;em&gt;after&lt;/em&gt; the refactoring. I was &lt;em&gt;sure&lt;/em&gt; the code was correct. After all, if it compiles, it works, right?&lt;/p&gt;
&lt;p&gt;And sure enough, the code &lt;em&gt;did&lt;/em&gt; work. I could open MRU files and old project directories from Kakoune, and I was quite pleased with myself.&lt;/p&gt;
&lt;p&gt;Of course, by now you should have guessed there&amp;rsquo;s a horrible performance bug in the code above. Did you spot it? If you did, congrats! I certainly did not at the time.&lt;/p&gt;
&lt;h1 id=&#34;part-5-the-peer-programming-session&#34;&gt;Part 5: The peer programming session&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#part-5-the-peer-programming-session&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The refactoring took place 6 months ago. I am using those tools at work, which means I was using those commands for 6 months, 5 days a week. The database files contained thousands of entries. The horrible bug was still there, consuming CPU cycles without a care in the world, and I did not notice anything.&lt;/p&gt;
&lt;p&gt;Fortunately, I did a peer programming session with one of my colleagues and something weird happened. He got &lt;em&gt;bored&lt;/em&gt; watching my zsh prompt getting stuck when I was using the &lt;code&gt;z&lt;/code&gt; and &lt;code&gt;ctrl-r&lt;/code&gt; shortcuts.&lt;/p&gt;
&lt;p&gt;I then measured the performance of my tools again and I found  that the &lt;code&gt;cmd-history list&lt;/code&gt; command took 1.7 &lt;strong&gt;seconds&lt;/strong&gt; to run.  That&amp;rsquo;s &lt;em&gt;one thousand and seven hundred&lt;/em&gt; milliseconds. It&amp;rsquo;s a &lt;strong&gt;very long&lt;/strong&gt; time. No wonder my colleague got bored! What&amp;rsquo;s amazing though is that I did &lt;em&gt;not&lt;/em&gt; notice anything wrong until he told me about it.&lt;/p&gt;
&lt;h1 id=&#34;part-6-the-fix&#34;&gt;Part 6: The fix&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#part-6-the-fix&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now it&amp;rsquo;s time to squash the bug. The culprit lies here, in the &lt;code&gt;Storage&lt;/code&gt; constructor:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries_collection: &lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;&amp;lt;EntriesCollection&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;path: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;std&lt;/span&gt;::path::PathBuf,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Storage&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;db_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;path.join(entries_collection.name());&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;read_db(&amp;amp;db_path);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;entries_collection.add(&amp;amp;entry);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;db_path,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;entries_collection,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;re reading each line of the database file, and passing it to &lt;code&gt;EntriesCollection.add()&lt;/code&gt;. This means we keep calling the &lt;code&gt;add()&lt;/code&gt; method over and over. It does not do much, but it still has to go through &lt;em&gt;all&lt;/em&gt; the entries when performing deduplication. This is a classic case of the &lt;a href=&#34;https://www.joelonsoftware.com/2001/12/11/back-to-basics/&#34;&gt;Shlemiel algorithm&lt;/a&gt; and it explains the abysmal performance of the tool as soon as the database gets big enough.&lt;/p&gt;
&lt;p&gt;I believe I wrote the code that way because I thought it would be nice to somehow &amp;ldquo;validate&amp;rdquo; the entries when reading the database. That way, if the algorithm in the &lt;code&gt;add&lt;/code&gt; method changed, the database will be &amp;ldquo;migrated&amp;rdquo; automatically (for instance, all non-existing paths still present in the db will automatically disappear). Another classical mistake named &lt;em&gt;&lt;abbr title=&#34;You Ain&#39;t Gonna Need It&#34;&gt;YAGNI&lt;abbr&gt;&lt;/em&gt;: it&amp;rsquo;s doubtful I&amp;rsquo;ll ever need to &amp;ldquo;migrate&amp;rdquo; the database, and when I need to, I&amp;rsquo;ll probably just have to write a tiny throw-away script to do it.&lt;/p&gt;
&lt;p&gt;Anyway, now that we&amp;rsquo;ve decided the &amp;ldquo;auto migrating&amp;rdquo; feature can go away, we can solve our performance issue by adding an &lt;code&gt;add_all&lt;/code&gt; method to the trait, and replacing the &lt;code&gt;for&lt;/code&gt; loop in the &lt;code&gt;Storage&lt;/code&gt; constructor:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;trait&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;     &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;+&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add_all&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;     &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;list&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries_collection: &lt;span style=&#34;color:#24909d&#34;&gt;Box&lt;/span&gt;&amp;lt;EntriesCollection&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;path: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;std&lt;/span&gt;::path::PathBuf,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Storage&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;db_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;path.join(entries_collection.name());&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;read_db(&amp;amp;db_path);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;-&lt;span style=&#34;color:#666&#34;&gt;       &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;-&lt;span style=&#34;color:#666&#34;&gt;           &lt;/span&gt;entries_collection.add(&amp;amp;entry);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;-&lt;span style=&#34;color:#666&#34;&gt;       &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;+&lt;span style=&#34;color:#666&#34;&gt;       &lt;/span&gt;entries_collection.add_all(entries);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Storage&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;db_path,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;entries_collection,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In turn, this means we need to implement the &lt;code&gt;add_all()&lt;/code&gt; method on all structs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Commands&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add_all&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;WorkingDirs&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add_all&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;EntriesCollection&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MruFiles&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add_all&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries: &lt;span style=&#34;color:#24909d&#34;&gt;Vec&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt;&amp;gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.entries&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entries;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;a-small-digression&#34;&gt;A small digression&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-small-digression&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Surely you&amp;rsquo;ve noticed the implementation of &lt;code&gt;add_all()&lt;/code&gt; is &lt;em&gt;exactly&lt;/em&gt; the same in the three structs. Why did not we add blanket implementation of the &lt;code&gt;add_all()&lt;/code&gt; method in the trait?&lt;/p&gt;
&lt;p&gt;Well, because we need access to the &lt;code&gt;entries&lt;/code&gt; field of the struct, and there&amp;rsquo;s no way to do that in Rust. Since I&amp;rsquo;m in love with Rust, I can rationalize this in several ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, the code duplication is not that a problem since there&amp;rsquo;s only one line of code.&lt;/li&gt;
&lt;li&gt;Second, the duplication is &lt;em&gt;incidental&lt;/em&gt;. We could imagine using a &lt;code&gt;Set&lt;/code&gt; instead of a &lt;code&gt;Vec&lt;/code&gt; to store the entries, and the trait does not need to know about this. Ditto if we decide to rename the field.&lt;/li&gt;
&lt;li&gt;Third, I can tell myself that this lacking feature is a good thing&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; because I&amp;rsquo;ve often been bitten in other languages when sharing class members through inheritance (both in C++ and Python).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take those how you want: I can tell myself those are good arguments, but you don&amp;rsquo;t have to believe me :)&lt;/p&gt;
&lt;h1 id=&#34;the-moral-of-the-story&#34;&gt;The moral of the story&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-moral-of-the-story&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here are my takeaways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When performance matters, don&amp;rsquo;t forget to measure it constantly, especially after refactorings (or even after each commit if you can afford to)&lt;/li&gt;
&lt;li&gt;The boiling frog metaphor is actually a good one, and you may be inside some boiling water without realizing it.&lt;/li&gt;
&lt;li&gt;And finally, listen to what people say to you when they tell you about something bad in your life. I actually felt something was off with my machine those last 6 months, but it took an other person to help me take a step back and understand what was wrong.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take care and see you another time!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;That&amp;rsquo;s because I was using a tool named &lt;code&gt;z&lt;/code&gt; before I decided to &lt;a href=&#34;https://dmerej.info/blog/post/rewriting-z-from-scratch/&#34;&gt;re-implement it myself&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;If you are wondering why, go read &lt;em&gt;&lt;a href=&#34;https://blog.codinghorror.com/rule-of-three/&#34;&gt;The Rule of Three&lt;/a&gt;&lt;/em&gt; on the Coding Horror blog.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;By the way, not all Rust users think this way. You can find a RFC about using fields in traits &lt;a href=&#34;https://github.com/nikomatsakis/fields-in-traits-rfc&#34;&gt;on GitHub&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Requests: What You Need To Build Useful Apps</title>
      <link>https://dmerej.info/blog/post/requests-what-you-need-to-build-useful-apps/</link>
      <pubDate>Wed, 24 Jul 2019 11:01:01 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/requests-what-you-need-to-build-useful-apps/</guid>
      <description>&lt;p&gt;&lt;em&gt;Today&amp;rsquo;s article has been written by guest Abdur-Rahmaan Janhangeer. He is Organising Member of the &lt;a href=&#34;http://www.pymug.com&#34;&gt;Python Mauritius User Group&lt;/a&gt;, Arabic Coordinator for the docs and maintainer of &lt;a href=&#34;http://www.pythonmembers.club&#34;&gt;pythonmembers.club&lt;/a&gt; and was kind enough to submit this article to be posted there.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Requests is a popular Python library. It has particularly been praised for its intuitive programming API. If you are new to Python, this should be a top priority in your learning path. Today we are going to give you some useful blocks to immediately get started! Have fun!&lt;/p&gt;
&lt;h2 id=&#34;just-how-popular-is-requests&#34;&gt;Just How Popular Is Requests?&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#just-how-popular-is-requests&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Requests gets &lt;a href=&#34;https://pypistats.org/packages/requests&#34;&gt;1M+ downloads&lt;/a&gt; per day, yes per day! That&amp;rsquo;s really crazy. It&amp;rsquo;s the lifetime download of an average package! It has also been used among others to help humanity see the first &lt;a href=&#34;https://github.com/achael/eht-imaging/blob/master/requirements.txt&#34;&gt;image of a blackhole&lt;/a&gt;. Sphinx, Celery and Tornado &lt;a href=&#34;https://libraries.io/pypi/requests&#34;&gt;also use it&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&#34;how-do-server-requests-work&#34;&gt;How Do Server Requests Work?&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#how-do-server-requests-work&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Requests get it&amp;rsquo;s name from requests made to servers. Servers always listen for requests to resources. You tell it: give me a packet of sugar, it looks for it, if found, it&amp;rsquo;ll tell: &amp;ldquo;ok! found it!&amp;rdquo;&amp;quot; else, it will tell: &amp;ldquo;oh oh not found&amp;rdquo;. In real life, your browser asks for images, webpages etc. Here are some types of requests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GET&lt;/li&gt;
&lt;li&gt;POST&lt;/li&gt;
&lt;li&gt;PUT&lt;/li&gt;
&lt;li&gt;DELETE&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most used type is the GET request. While opening a normal webpage, your browser makes a GET request.&lt;/p&gt;
&lt;h2 id=&#34;comparing-normal-code-to-requests-code&#34;&gt;Comparing Normal Code To Requests Code&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#comparing-normal-code-to-requests-code&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is what you&amp;rsquo;ll do to get a byte representation of a webpage (which gives the page source).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;urllib.request&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;content = urllib.request.urlopen(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://dmerej.info&amp;#34;&lt;/span&gt;).read()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(content)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;with requests (it&amp;rsquo;s pip install requests), you do&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;requests&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;req = r.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://dmerej.info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(req.content)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;req has many attributes to try. Let&amp;rsquo;s explore some!&lt;/p&gt;
&lt;h2 id=&#34;requests-exploration&#34;&gt;Requests Exploration&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#requests-exploration&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Try the following in a shell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;requests&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; req = r.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://dmerej.info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; req.text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; req.status_code &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# 200 means ok!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; req.reason
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; req.text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; req.content
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;start-cooking-using-beautiful-soup&#34;&gt;Start Cooking: Using Beautiful Soup&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#start-cooking-using-beautiful-soup&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a BeautifulSoup snippet usage with requests:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;bs4&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; BeautifulSoup
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;requests&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;req = r.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://dmerej.info&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;soup = BeautifulSoup(req.content, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;html.parser&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(soup.text)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a side note, if you have a url like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;http://modifyme.org?name=dimitri
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;you can make a get request like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;req = r.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;http://modifyme.org&amp;#39;&lt;/span&gt;, params={&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;dimitri&amp;#39;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and you will get the same thing.&lt;/p&gt;
&lt;h2 id=&#34;getting-json-data&#34;&gt;Getting JSON data&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#getting-json-data&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;JSON data are similar to Python dictionaries. Here is a snippet to try out:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;requests&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;req = r.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://randomuser.me/api/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(req.json())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s an api that generates fake user data. &lt;code&gt;req.json()&lt;/code&gt; returns a Python dictionary ready to use.&lt;/p&gt;
&lt;h2 id=&#34;download-file&#34;&gt;Download File&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#download-file&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a function that downloads a file where you want, given the url:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;download_file&lt;/span&gt;(file_url, path):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r = requests.get(file_url, allow_redirects=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;open&lt;/span&gt;(path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;).write(r.content)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since &lt;code&gt;r.content&lt;/code&gt; returns a byte object, we write the file in &lt;code&gt;wb&lt;/code&gt; (write binary) mode, thus getting our file. It works for any file url. Try it!&lt;/p&gt;
&lt;h2 id=&#34;upload-file&#34;&gt;Upload File&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#upload-file&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;POST requests are used to send data to the server, a typical post requests look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;r.post(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;http://www.example.com/verify_login&amp;#39;&lt;/span&gt;, data={&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;moi&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;password&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;1234&amp;#39;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s say while disseting a form you get a form using POST to upload a file which looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;form&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;action&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/upload&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;method &lt;/span&gt;= &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;enctype&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;multipart/form-data&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;name&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;file_to_upload&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;input&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;type&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;/&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;form&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can write a script like this to upload a file, an image in this case:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;requests&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;files = {&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;file&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#24909d&#34;&gt;open&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;path_to&amp;gt;/image.png&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;)}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;req = r.post(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;http://www.example.com/upload&amp;#34;&lt;/span&gt;, files=files)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(req.text)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above snippet is useful if you have to upload to your own custom backend. But, in the real world, sites add some input values with different name attributes to detect automatic submissions and you might have to modify to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;r.post(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;http://www.example.com/upload&amp;#34;&lt;/span&gt;, files=files, data={&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;name&amp;gt;&amp;#39;&lt;/span&gt;:&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;value&amp;gt;&amp;#39;&lt;/span&gt;,})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;caveats-to-look-for&#34;&gt;Caveats To Look For&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#caveats-to-look-for&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It should be born in mind that requests does not execute the JavaScript on a web page. If you are doing webscraping, there are other tools like Selenium.&lt;/p&gt;
&lt;p&gt;Requests in an incredible tool to add to your arsenal, make good use of it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>dmerej.info: now also in French</title>
      <link>https://dmerej.info/blog/post/dmerej-info-in-french/</link>
      <pubDate>Sun, 05 May 2019 16:16:35 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/dmerej-info-in-french/</guid>
      <description>&lt;p&gt;Hello there,&lt;/p&gt;
&lt;p&gt;Just a quick note to let you know I&amp;rsquo;m now also producing contents in French, at &lt;a href=&#34;https://dmerej.info/blog/fr&#34;&gt;https://dmerej.info/blog/fr&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you do speak French, you can read more about it in &lt;a href=&#34;https://dmerej.info/blog/fr/post/bonjour-monde/&#34;&gt;the introductory post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>The virtue of incremental development</title>
      <link>https://dmerej.info/blog/post/the-virtue-of-incremental-development/</link>
      <pubDate>Sun, 21 Apr 2019 12:10:49 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/the-virtue-of-incremental-development/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s today challenge: can you write a command-line tool that
allows converting to and from various measurements units?&lt;/p&gt;
&lt;p&gt;For instance, you could input &amp;ldquo;3 miles in meters&amp;rdquo; and get
&amp;ldquo;4828.03&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I submitted this challenge to my Python students last weekend,
asking them to write the code from scratch. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;1 hour later, something miraculous happened that I never
would have expect.&lt;/p&gt;
&lt;p&gt;But let me tell you the full story.&lt;/p&gt;
&lt;h1 id=&#34;getting-started&#34;&gt;Getting started&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#getting-started&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I told the students that they could start by writing some &amp;ldquo;exploratory code&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Just hard-code anything you have to and keep everything in the &lt;code&gt;main()&lt;/code&gt; function &amp;ldquo;, I said.&lt;/p&gt;
&lt;p&gt;After a few discussions, we agreed to only write code that converted kilometers to miles, and that
we&amp;rsquo;ll read the values from the command line.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what we came up with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    kilometers = &lt;span style=&#34;color:#24909d&#34;&gt;float&lt;/span&gt;(sys.argv)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    miles = kilometers / &lt;span style=&#34;color:#3677a9&#34;&gt;1.609&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;.2&lt;/span&gt;f&lt;span style=&#34;color:#ed9d13&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;, miles)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; __name__ == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then pointed out that the code was not generic. Indeed, &amp;ldquo;kilometers&amp;rdquo;, &amp;ldquo;miles&amp;rdquo; and &amp;ldquo;1.609&amp;rdquo; are hard-coded there.&lt;/p&gt;
&lt;h1 id=&#34;naming-a-new-function&#34;&gt;Naming a new function&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#naming-a-new-function&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The students understood there was a three-parameters function waiting to be written. So we went to the drawing board
and after a while we decided to have a function called &lt;code&gt;convert(value, unit_in, unit_out)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that we did &lt;em&gt;not&lt;/em&gt; make any assumption about the &lt;em&gt;body&lt;/em&gt; of the function. We just wanted to see how &lt;code&gt;main()&lt;/code&gt; could become
more generic, and we were still allowed to hard-code parts of the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;convert&lt;/span&gt;(value, unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    coefficient = &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt; / &lt;span style=&#34;color:#3677a9&#34;&gt;1.609&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result = value * coefficient
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    value = &lt;span style=&#34;color:#24909d&#34;&gt;float&lt;/span&gt;(sys.argv[&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unit_in = sys.argv[&lt;span style=&#34;color:#3677a9&#34;&gt;2&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    unit_out = sys.argv[&lt;span style=&#34;color:#3677a9&#34;&gt;3&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result = convert(value, unit_in, unit_out)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;.2&lt;/span&gt;f&lt;span style=&#34;color:#ed9d13&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;, result)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;main()&lt;/code&gt; function is now completely &lt;em&gt;generic&lt;/em&gt;, and we probably won&amp;rsquo;t need to change it.&lt;/li&gt;
&lt;li&gt;The signature of the &lt;code&gt;convert&lt;/code&gt; function almost dictated the command-line syntax:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;convert&lt;/span&gt;(value, unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Usage: convert.py value unit_in unit_out&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ python3 convert.py &lt;span style=&#34;color:#3677a9&#34;&gt;2&lt;/span&gt; meters miles
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;computing-the-coefficient&#34;&gt;Computing the coefficient&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#computing-the-coefficient&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now it was time to get rid of the hard-coded coefficient. This time finding a function name was easier:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_coefficient&lt;/span&gt;(unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we tried to figure out how to implement it. We knew we would be needing a dictionary, but the structure of it was
unknown.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Back to the drawing board&amp;rdquo;, I said. &amp;ldquo;Let&amp;rsquo;s write down what the dictionary should look like&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s our first attempt:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;units =  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1.609&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;meters&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;, ....},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1760&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;meters&amp;#34;&lt;/span&gt;: ..., &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: ...}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;This won&amp;rsquo;t do&amp;rdquo;, I said. &amp;ldquo;Look at what happens if we add a new measurement unit, such as &lt;code&gt;feet&lt;/code&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll have to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;add a new &amp;lsquo;feet&amp;rsquo; key to the &lt;code&gt;units&lt;/code&gt; dictionary,&lt;/li&gt;
&lt;li&gt;compute all the coefficient to convert from &lt;code&gt;feet&lt;/code&gt; to all the other units,&lt;/li&gt;
&lt;li&gt;and add a &lt;code&gt;feet&lt;/code&gt; key to all the other dictionaries&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There has to be a better way!&lt;/p&gt;
&lt;p&gt;After a short brainstorming session, we decided to limit ourselves to &lt;em&gt;distance&lt;/em&gt; measurements, and to &lt;em&gt;always convert to SI units&lt;/em&gt; first.&lt;/p&gt;
&lt;p&gt;So we draw the new structure of the &lt;code&gt;units&lt;/code&gt; dictionary:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Coefficients convert from &amp;#34;meters&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;distances = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1.094&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1609&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then we thought about the algorithm. We found three possibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If we want to convert &lt;em&gt;from meters&lt;/em&gt;, we just have to look up the coefficient in the dictionary&lt;/li&gt;
&lt;li&gt;If we want to convert &lt;em&gt;to meters&lt;/em&gt;, we can look up the coefficient in the dictionary and return its inverse&lt;/li&gt;
&lt;li&gt;Otherwise, we combine the two procedures above and return the product of the two coefficients.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;ldquo;This is looking good&amp;rdquo;, I said. &amp;ldquo;Let&amp;rsquo;s try to implement the algorithm but just for the first case and see what happens&amp;rdquo;.&lt;/p&gt;
&lt;h1 id=&#34;testing-the-algorithm&#34;&gt;Testing the algorithm&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#testing-the-algorithm&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I showed my students how they could use Python&amp;rsquo;s interpreter to check the get_coefficient() function was working properly.&lt;/p&gt;
&lt;p&gt;We quickly managed to get the first case working:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_coefficient&lt;/span&gt;(unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# FIX ME: only works with distances for now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Coefficients to convert from &amp;#34;meters&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    distances = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1.094&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1609&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; unit_in == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; distances[unit_out]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;conversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; conversion.get_coefficient(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;0.001&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; conversion.get_coefficient(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;1.094&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;Cool, this works&amp;rdquo;, I said. &amp;ldquo;Let&amp;rsquo;s see what happens when the input value is not in meters:&amp;rdquo;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_coefficient&lt;/span&gt;(unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# FIX ME: only works with distances for now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Coefficients to convert from &amp;#34;meters&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    distances = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1.094&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1609&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; unit_in == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; distances[unit_out]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        reciprocal_coefficient = &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt; / distances[unit_in]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; reciprocal_coefficient * distances[unit_out]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;conversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; conversion.get_coefficient(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;1760&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;Look how readable the code is&amp;rdquo;, I said. &amp;ldquo;We have a value that&amp;rsquo;s called
&lt;code&gt;reciprocal_coefficient&lt;/code&gt; and we get it by calling 1 over something else. Isn&amp;rsquo;t
this nice?&amp;rdquo;.&lt;/p&gt;
&lt;h1 id=&#34;the-miracle&#34;&gt;The miracle&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-miracle&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I then pointed out that the &lt;a href=&#34;https://dmerej.info/blog/post/else-after-return-yea-or-nay/&#34;&gt;&amp;rsquo;else&amp;rsquo; after the return&lt;/a&gt; was unnecessary.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_coefficient&lt;/span&gt;(unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# FIX ME: only works with distances for now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Coefficients to convert from &amp;#34;meters&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    distances = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1.094&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1609&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; unit_in == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; distances[unit_out]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    reciprocal_coefficient = &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt; / distances[unit_in]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; reciprocal_coefficient * distances[unit_out]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then it happened. &amp;ldquo;Hey&amp;rdquo;, one of the students said, &amp;ldquo;what if we added meters in the distances dictionary with &lt;code&gt;1&lt;/code&gt; as value?
We could get rid of the first &lt;code&gt;if&lt;/code&gt; too!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Let&amp;rsquo;s do it&amp;rdquo;, I said:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_coefficient&lt;/span&gt;(unit_in, unit_out):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# FIX ME: only works with distances for now&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    distances = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1.094&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;miles&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;/&lt;span style=&#34;color:#3677a9&#34;&gt;1609&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    reciprocal_coefficient = &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt; / distances[unit_in]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; reciprocal_coefficient * distances[unit_out]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;conversion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; conversion.get_coefficient(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; conversion.get_coefficient(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;km&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;1000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; conversion.get_coefficient(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yards&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;1760&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And of course, this works. When &lt;code&gt;meters&lt;/code&gt; is either &lt;code&gt;unit_in&lt;/code&gt; or &lt;code&gt;unit_out&lt;/code&gt;, all operations will involve multiplying or dividing by 1.&lt;/p&gt;
&lt;p&gt;That was a really nice surprise for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One, when I thought about the problem alone, before starting the workshop, I was pretty sure I would need a much more complex data structure.&lt;/li&gt;
&lt;li&gt;Two, one of the students just refused to believe the code would work, even after having seen it in action in the interpreter ;)&lt;/li&gt;
&lt;li&gt;Three, we killed one comment :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;lessons-learned&#34;&gt;Lessons learned&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#lessons-learned&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We found a beautiful algorithm and a nice data structure, not by trying to
solve &lt;em&gt;everything&lt;/em&gt; at once, but by slowly building up more and more generic
code, getting rid of hard-coded values one after the other, and by carefully
thinking about naming.&lt;/p&gt;
&lt;p&gt;I hope you find this approach useful, and I highly suggest you try using it
next time you implement a new feature.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I&amp;rsquo;m using &lt;a href=&#34;https://en.wikipedia.org/wiki/Mob_programming&#34;&gt;mob programming&lt;/a&gt; during my Python classes. It works really well.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Crafting command line outputs</title>
      <link>https://dmerej.info/blog/post/crafting-command-line-outputs/</link>
      <pubDate>Mon, 25 Mar 2019 13:55:26 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/crafting-command-line-outputs/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve used many command line tools. It always makes me feel happy when I come across a tool that has a nice, usable and friendly output. I always try to make those I create or maintain as good as possible in this regard.&lt;/p&gt;
&lt;p&gt;Along the way, I&amp;rsquo;ve learned a few tricks I&amp;rsquo;d like to share with you.&lt;/p&gt;
&lt;h1 id=&#34;start-with-the-contents&#34;&gt;Start with the contents&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#start-with-the-contents&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When designing command line output, start with the &lt;em&gt;contents&lt;/em&gt;, not the style.
In other words, think about &lt;em&gt;what&lt;/em&gt; to print before thinking about &lt;em&gt;how&lt;/em&gt; to print it - this is helpful in a lot of other situations.&lt;/p&gt;
&lt;h1 id=&#34;error-messages&#34;&gt;Error messages&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#error-messages&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The absolute minimum your command line tool needs are &lt;em&gt;good error messages&lt;/em&gt;.
Pay attention to those -  good error messages can go a long way in helping your users and may even save you from having to answer a bunch of bug reports! &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;A good error message should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start with a clear summary describing what went wrong&lt;/li&gt;
&lt;li&gt;Contain as many details as relevant (but not too much)&lt;/li&gt;
&lt;li&gt;And possibly a suggestion on how to fix the issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bad example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Could not open cfg file. ENOENT 2
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Good example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Error while reading config file (~/.config/foo.cfg)
Error was: No such file or directory
Please make sure the file exists and try again
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;standard-out-and-standard-error&#34;&gt;Standard out and standard error&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#standard-out-and-standard-error&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Speaking of error messages, note that your can choose to write text to &lt;em&gt;two&lt;/em&gt; different channels (often called &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; for short). Use &lt;code&gt;stderr&lt;/code&gt; for error messages and error messages only. People sometimes need to hide &amp;ldquo;normal&amp;rdquo; messages from your tool, but they&amp;rsquo;ll need to know about those errors!&lt;/p&gt;
&lt;h1 id=&#34;colors&#34;&gt;Colors&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#colors&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Things to know about colors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use red for errors (that&amp;rsquo;s about the only convention I know of which is somewhat followed by everyone).&lt;/li&gt;
&lt;li&gt;You can get a lot of meaning out of simple, ASCII-art decoration. Don&amp;rsquo;t necessarily reach from emojis immediately 😜.&lt;/li&gt;
&lt;li&gt;Try to use colors in a &lt;em&gt;consistent&lt;/em&gt; way. Having helper methods like &lt;code&gt;print_error()&lt;/code&gt;, &lt;code&gt;print_message ()&lt;/code&gt; can help.&lt;/li&gt;
&lt;li&gt;On Linux and macOS, coloring is achieved by emitting certain non-printable ASCII characters (sometimes referred to as ANSI escape codes). This is fine when your program runs in a terminal, but &lt;em&gt;not&lt;/em&gt; when its output is redirected to a file, for instance.&lt;/li&gt;
&lt;li&gt;People usually expect color activation to be controlled with a tri-state: &amp;ldquo;always&amp;rdquo;, &amp;ldquo;never&amp;rdquo;, or &amp;ldquo;auto&amp;rdquo;. The first two are self-explanatory, but &amp;ldquo;auto&amp;rdquo; needs some explaining.&lt;/li&gt;
&lt;li&gt;When &amp;ldquo;auto&amp;rdquo; is set, your program should decide whether to use colors by itself. You can do so by calling &lt;code&gt;isatty(stdout)&lt;/code&gt; or something equivalent.&lt;/li&gt;
&lt;li&gt;On Windows, coloring is achieved by using the win32 API, but the same ideas apply.&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s probably a library near you that implements all of this. Even if it does not seem much, there&amp;rsquo;s no point in re-inventing the wheel here.&lt;/li&gt;
&lt;li&gt;Finally, try to follow the &lt;a href=&#34;https://bixense.com/clicolors/&#34;&gt;CLICOLORS standard&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;progress&#34;&gt;Progress&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#progress&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;If your comman-line tool does some lengthy work, you should output &lt;em&gt;something&lt;/em&gt;  to your users so that they know your program is not stuck.&lt;/p&gt;
&lt;p&gt;The best possible progress indicator contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An ETA&lt;/li&gt;
&lt;li&gt;A progress bar&lt;/li&gt;
&lt;li&gt;A speed indicator&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;wget&lt;/code&gt; does that really well. Your favorite language probably has one or two ready-to-use libraries for this.&lt;/p&gt;
&lt;p&gt;If you can&amp;rsquo;t achieve the full progress bar, as a lightweight alternative you can just display a counter: (&lt;code&gt;1/10&lt;/code&gt;, &lt;code&gt;2/10&lt;/code&gt;, etc.). If you do so, please make sure the user knows &lt;em&gt;what is being counted&lt;/em&gt; !&lt;/p&gt;
&lt;h1 id=&#34;remove-noise&#34;&gt;Remove noise&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#remove-noise&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We already saw that people maybe running your tool without a terminal attached. In this case, you should skip displaying progress bars and the like.&lt;/p&gt;
&lt;p&gt;Also, try to remove things that are only useful when debugging (or don&amp;rsquo;t display them by default).&lt;/p&gt;
&lt;p&gt;This includes the time taken to perform a given action (unless it&amp;rsquo;s useful to the end-user, like if you are writing a test runner for instance). Also, don&amp;rsquo;t forget that users can and will prefix their command line with &lt;code&gt;time&lt;/code&gt; to get precise results if they need to.&lt;/p&gt;
&lt;p&gt;A good technique to remove noise is to completely erase the last line before writing a new one.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how to do it in Python:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;size = shutil.get_terminal_size()   &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# get the current size of the terminal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(first_message, end=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;do_something()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; * size.columns, end=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;)  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# fill up the line with blanks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# so that lines don&amp;#39;t overlap&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(second_message)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, this only works if the user does not need to know about the whole suite of messages!&lt;/p&gt;
&lt;h1 id=&#34;tests&#34;&gt;Tests&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#tests&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;End-to-end tests are a great way to tweak the output without having to do a bunch of setup by hand, &lt;em&gt;and&lt;/em&gt; check the error messages look good.&lt;/p&gt;
&lt;h1 id=&#34;parting-words&#34;&gt;Parting words&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#parting-words&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Well, that&amp;rsquo;s all I&amp;rsquo;ve got today. Please keep those tips in mind when creating your own command line tool, and if you find a program that does not adhere to these rules, feel free to send patches. Until next time!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Assuming they take the time to &lt;em&gt;read&lt;/em&gt; the output. But the better they are, the more they&amp;rsquo;re likely to get read :)&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>My Blogging Flow - Part 2 - Publishing</title>
      <link>https://dmerej.info/blog/post/my-blogging-flow-part-2-publishing/</link>
      <pubDate>Thu, 07 Feb 2019 12:14:20 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/my-blogging-flow-part-2-publishing/</guid>
      <description>&lt;p&gt;Welcome to part 2 of &amp;ldquo;How this blog gets written&amp;rdquo;. If you haven&amp;rsquo;t already, feel free to read &lt;a href=&#34;https://dmerej.info/blog/post/my-blogging-flow-part-1-under-the-hood/&#34;&gt;part 1&lt;/a&gt; first :)&lt;/p&gt;
&lt;h1 id=&#34;the-idea&#34;&gt;The Idea&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-idea&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Everything starts with an idea. I have a small git repository on my dedicated machine which contains a bunch of markdown files, one per article. (This repository is private by the way).&lt;/p&gt;
&lt;p&gt;The contents of these files can vary from just a few lines to an almost complete article. Most of the time they only contain a basic outline though.&lt;/p&gt;
&lt;p&gt;I update the &lt;code&gt;ideas&lt;/code&gt; repository as soon as ideas come. It&amp;rsquo;s important to write things down as soon as possible. Forgetting what you wanted to say or how you wanted to say it happens far more quickly than you would think.&lt;/p&gt;
&lt;h1 id=&#34;the-first-draft&#34;&gt;The first draft&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-first-draft&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Next, it&amp;rsquo;s time to start writing the full article. I have a small Python script which:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;finds out the next article number and fill up the front matter for me (because I&amp;rsquo;m lazy)&lt;/li&gt;
&lt;li&gt;runs &lt;code&gt;git add&lt;/code&gt; on the generated Markdown file so I don&amp;rsquo;t delete it by mistake by running &lt;code&gt;git clean&lt;/code&gt; (because mistakes happen)&lt;/li&gt;
&lt;li&gt;opens the Markdown file in my text editor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it&amp;rsquo;s time to draft the article. I&amp;rsquo;ve configured my editor so that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;spell checking is activated&lt;/li&gt;
&lt;li&gt;syntax highlighting is disabled (I&amp;rsquo;ve explained why &lt;a href=&#34;https://dmerej.info/blog/post/syntax-highlighting-is-useless/&#34;&gt;in a previous blog post&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In an other terminal (usually hidden behind a tab), I have &lt;code&gt;hugo serve&lt;/code&gt; running, and finally, next to the text editor, a web browser, so that I can see the changes happening in real time.&lt;/p&gt;
&lt;h1 id=&#34;proofreading&#34;&gt;Proofreading&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#proofreading&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;And then it&amp;rsquo;s time to proofread, proofread, proofread &amp;hellip;&lt;/p&gt;
&lt;p&gt;I usually wait for a good night&amp;rsquo;s sleep before re-reading an article.&lt;/p&gt;
&lt;p&gt;If the article is really big and complex, I sometimes open a pull request on GitHub and ask friends or colleagues to review it.&lt;/p&gt;
&lt;p&gt;I do my proofread both in my text editor and in the browser, to increase the chance I&amp;rsquo;ll see spelling errors, awkward formulations, transitions problems and the like.&lt;/p&gt;
&lt;h1 id=&#34;publishing&#34;&gt;Publishing&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#publishing&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I have another Python script to automate publication. Here&amp;rsquo;s what it does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;make an automatic commit in case I forgot (the script just skips this part if the repository is clean)&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;hugo --buildDrafts=false&lt;/code&gt; to build the HTML files&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;rsync&lt;/code&gt; to upload them to my server&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;git push&lt;/code&gt; to publish changes to GitHub&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that the publishing of a new post triggers a new version of the blog&amp;rsquo; feed to be written.&lt;/p&gt;
&lt;p&gt;This script can be run after any corrections to an already published article.&lt;/p&gt;
&lt;p&gt;When a brand new article has just been published, I run yet an other Python script to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parse the RSS feed and find out the URL and title of the latest article&lt;/li&gt;
&lt;li&gt;Write an automatic tweet like &lt;a href=&#34;https://twitter.com/d_merej/status/1092029859864416259&#34;&gt;this one&lt;/a&gt; (the additional hashtags at the end are given on the command line)&lt;/li&gt;
&lt;li&gt;Write a toot on mastodon with similar content&lt;/li&gt;
&lt;li&gt;Send an email to the people who subscribed to &lt;a href=&#34;https://dmerej.info/blog/post/introducing-dmerej-newsletter/&#34;&gt;the newsletter&lt;/a&gt;. I manually maintain a list of subscribers inside a configuration file for now, since there&amp;rsquo;s no subscription form on the blog.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;devto&#34;&gt;dev.to&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#devto&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Then it&amp;rsquo;s time to wait until &lt;code&gt;dev.to&lt;/code&gt; picks up the latest version of the RSS feed, parses the HTML from the feed, converts it back to markdown and add it into my dashboard.&lt;/p&gt;
&lt;p&gt;(Yup, you can configure &lt;code&gt;dev.to&lt;/code&gt; to do this!)&lt;/p&gt;
&lt;p&gt;This works quite well given the weird round-trip through HTML. Still, I have to re-read the markdown created by the dev.to importer just in case. This gives me a final opportunity to proofread the article one last time.&lt;/p&gt;
&lt;h1 id=&#34;feedback&#34;&gt;Feedback&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#feedback&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Thanks to isso I get notified when new comments are posted. I also of course get notifications from dev.to.&lt;/p&gt;
&lt;p&gt;When I&amp;rsquo;m lucky, &lt;a href=&#34;https://twitter.com/thepracticaldev&#34;&gt;@thepracticaldev&lt;/a&gt; tweets a link to my article, and I get new followers and more views. This is nice :)&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all folks! If you have any other questions regarding how the blog works, don&amp;rsquo;t be afraid to ask in the comments below!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2020-07-20 update: I&amp;rsquo;ve published a &lt;a href=&#34;https://gist.github.com/dmerejkowsky/d105bbf82b7746bf60b044ebd1c5fef8&#34;&gt;gist on GitHub&lt;/a&gt; containing the relevant part of the Python code mentioned above&lt;/em&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My Blogging Flow - Part 1 - Under the hood</title>
      <link>https://dmerej.info/blog/post/my-blogging-flow-part-1-under-the-hood/</link>
      <pubDate>Wed, 06 Feb 2019 11:46:32 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/my-blogging-flow-part-1-under-the-hood/</guid>
      <description>&lt;p&gt;Several people have asked me how my blog works and how it gets written, so here&amp;rsquo;s a blog post about how I blog (so meta).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start at the beginning.&lt;/p&gt;
&lt;h1 id=&#34;the-history-of-dmerejinfoblog&#34;&gt;The history of dmerej.info/blog&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-history-of-dmerejinfoblog&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&#34;buying-a-dns-domain&#34;&gt;Buying a DNS domain&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#buying-a-dns-domain&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first step was to buy a domain name. I chose &lt;a href=&#34;https://www.gandi.net/en&#34;&gt;gandi.net&lt;/a&gt; because I only heard good things about their registration service. I like the &amp;ldquo;retro&amp;rdquo; feel of the &lt;code&gt;.info&lt;/code&gt; &lt;abbr title=&#34;Top Level Domain&#34;&gt;TLD&lt;/abbr&gt;, and the &lt;code&gt;dmerej&lt;/code&gt; prefix is the one I use to shorten my name. Wether it&amp;rsquo;s a good thing or not, it&amp;rsquo;s too late to change it now, so there.&lt;/p&gt;
&lt;h2 id=&#34;getting-my-own-machine&#34;&gt;Getting my own machine&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#getting-my-own-machine&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I always wanted to control all aspects regarding the hosting of my blog, so I started by looking for a dedicated machine.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re not familiar with the concept, having a dedicated machine means that you pay for the hardware and ssh access to a server owned by soneone else. In exchange, you get to install and configure everything by hand. If it sounds like a loosy deal to you, remember that &lt;a href=&#34;https://dmerej.info/blog/post/a-definition-of-the-linux-desktop/&#34;&gt;I value control over convenience&lt;/a&gt; :)&lt;/p&gt;
&lt;p&gt;Anyway, I bought a server at a company called dedibox. (For the sake of completeness, I must say I&amp;rsquo;m now hosted by the nice people at &lt;a href=&#34;https://www.digitalocean.com&#34;&gt;Digital Ocean&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;But enough speaking about hosting services, let&amp;rsquo;s talk about blog engines!&lt;/p&gt;
&lt;h2 id=&#34;static-or-dynamic&#34;&gt;Static or dynamic&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#static-or-dynamic&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are two types of blog engines: &lt;em&gt;static&lt;/em&gt; and &lt;em&gt;dynamic&lt;/em&gt;. It has to do with what happens when a visitor requests the article&amp;rsquo;s URL.&lt;/p&gt;
&lt;p&gt;In a dynamic blog engine, the contents of each article is typically stored in a database, and the HTML is generated by the engine for each visitor. This means the server has to run some code for each visit.&lt;/p&gt;
&lt;p&gt;On the other hand, a &amp;ldquo;static&amp;rdquo; engine typically generates a bunch of HTML files from sources written in a markup language (often Markdown) &lt;em&gt;beforehand&lt;/em&gt;. Then all the server has to do is to present the correct file when a visitor wants to view a page.&lt;/p&gt;
&lt;p&gt;Both of them have pros and cons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Dynamic blog engines can handle comments, compute statistics (like view count), and so on. But because they require a database and some programming language support, they can get hard to deploy. Finding a way to do backups properly can get tricky, too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Static blogs cannot handle comments or anything like that, but they are &lt;em&gt;very easy&lt;/em&gt; to deploy: you can simply use existing web servers (like &lt;code&gt;nginx&lt;/code&gt; or &lt;code&gt;apache&lt;/code&gt;) directly. Also, backup is easy - you just need to backup the source files, and a &lt;code&gt;git&lt;/code&gt; repository is more than enough.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;finding-a-blog-engine&#34;&gt;Finding a blog engine&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#finding-a-blog-engine&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I must say I spent way too much time finding the engine I would use for my blog.&lt;/p&gt;
&lt;p&gt;My guts told me I wanted a static engine, so I started fiddling with many static blog generators. Alas, they are &lt;em&gt;tons&lt;/em&gt; of static engines out there, and I almost gave up on finding the one I would use - there were simply too much choice.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s when I realized I was not tackling the problem correctly: I was worried on &lt;em&gt;how to publish contents&lt;/em&gt;, but said content was &lt;em&gt;yet to be written!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So I took a look at dynamic blog engines (less choice there), found Dotclear almost by chance, and started to write.&lt;/p&gt;
&lt;p&gt;Finally, my articles were online and publicly readable by anyone on the world. What a joy!&lt;/p&gt;
&lt;p&gt;Advice to my dear readers: if you want to publish something online, don&amp;rsquo;t make my mistake: make sure you have &lt;em&gt;some&lt;/em&gt; contents before worrying about its publication.&lt;/p&gt;
&lt;h2 id=&#34;the-dotclear-period&#34;&gt;The Dotclear period&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-dotclear-period&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Configuring &lt;code&gt;php&lt;/code&gt; for Dotclear was a bit tedious, but once it was done I must admit it was quite pleasant to use. The admin view is rich and featureful, and the editing form is ergonomic. Comments are supported out of the box, and they are easy to moderate.&lt;/p&gt;
&lt;p&gt;But I still I had a problem: I was receiving many notifications about comments but &lt;em&gt;almost all of them were spam&lt;/em&gt; :/&lt;/p&gt;
&lt;p&gt;This was depressing, so I shut down the comment service and started looking for an alternative.&lt;/p&gt;
&lt;h2 id=&#34;the-hugo-period&#34;&gt;The Hugo period&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-hugo-period&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I went back looking for static engines, and found Hugo on &lt;a href=&#34;https://www.staticgen.com/&#34;&gt;the StaticGen engine comparison website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I immediately liked it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are many beautiful themes available. (Dotclear themes are nice too, but they look a tad outmoded to me).&lt;/li&gt;
&lt;li&gt;Hugo is easy to install (just one binary)&lt;/li&gt;
&lt;li&gt;Its documentation is complete and easy to follow&lt;/li&gt;
&lt;li&gt;I no longer had to setup &lt;code&gt;php&lt;/code&gt; on my server. Just a few lines of &lt;code&gt;nginx&lt;/code&gt; configuration was enough.&lt;/li&gt;
&lt;li&gt;Plus it is ridiculously &lt;em&gt;fast&lt;/em&gt;. It can build more than one hundred pages in less than one second.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To work, Hugo need a &lt;em&gt;theme&lt;/em&gt;.  A Hugo theme is made of various &lt;em&gt;templates&lt;/em&gt;, which control how the HTML gets produced, and some &lt;em&gt;static files&lt;/em&gt; (like CSS or images) that needs to be copied along the generated files.&lt;/p&gt;
&lt;p&gt;Hugo does not come with a default theme, so after a few tries, I settled on &lt;a href=&#34;https://themes.gohugo.io/blackburn/&#34;&gt;blackburn&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;writing-my-own-shortcode&#34;&gt;Writing my own shortcode&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#writing-my-own-shortcode&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The nice thing about Hugo is that you can customize the look and feel of your blog as much as you like. I still remember fondly the day I managed to implement the &amp;ldquo;movie script look&amp;rdquo; for the short scenes I wrote in &lt;a href=&#34;https://dmerej.info/blog/post/heard-and-seen-at-fosdem-2017/#scenes&#34;&gt;Heard and Seen at FOSDEM 2017&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how it works.&lt;/p&gt;
&lt;p&gt;First, I have custom &lt;code&gt;scene&lt;/code&gt; shortcode inside the &lt;code&gt;layouts/shortcode&lt;/code&gt; directory of the theme:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go-html-template&#34; data-lang=&#34;go-html-template&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;scene&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;{{&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;.Get&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;{{&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;.Inner&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;|&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;markdownify&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows me to write things like this in the Markdown source &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{〈 scene title=&amp;#34;Resurrecting Dinosaurs&amp;#34; 〉}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SPEAKER: I did &lt;span style=&#34;font-style:italic&#34;&gt;*not*&lt;/span&gt; expect to have a win32 architecture slide here at FOSDEM
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{〈 /scene 〉}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When Hugo sees the &lt;code&gt;scene&lt;/code&gt; directive it will generate HTML code containing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; and its special &lt;code&gt;scene&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;title&lt;/code&gt; inside the &lt;code&gt;h1&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;And the text inside the &lt;code&gt;scene&lt;/code&gt; directive, interpreted as Markdown too:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;div&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;class&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;scene&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Resurecting Dinosaurs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;h1&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SPEAKER: I did &amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;em&lt;/span&gt;&amp;gt;not&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;em&lt;/span&gt;&amp;gt; expect to have a win32 architecture slide
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;here at FOSDEM.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, I have a bit of CSS to render the &lt;code&gt;div&lt;/code&gt; properly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-scss&#34; data-lang=&#34;scss&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;.scene&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#bbb&#34;&gt;font-family&lt;/span&gt;: monospace;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#bbb&#34;&gt;line-height&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;.2&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;h1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#bbb&#34;&gt;line-height&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;.5&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#bbb&#34;&gt;font-size&lt;/span&gt;: &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;.2&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;em&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#bbb&#34;&gt;font-style&lt;/span&gt;: bold;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#bbb&#34;&gt;text-align&lt;/span&gt;: center;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s all there is to it :)&lt;/p&gt;
&lt;h3 id=&#34;switching-to-a-new-theme&#34;&gt;Switching to a new theme&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#switching-to-a-new-theme&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After a while, I was getting tired with &lt;code&gt;blackburn&lt;/code&gt;. Its CSS files were not easy to edit, it also had big dependencies like &lt;code&gt;font-awesome&lt;/code&gt; or Yahoo&amp;rsquo;s &lt;code&gt;Pure CSS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So I switched to &lt;a href=&#34;https://themes.gohugo.io/minimo/&#34;&gt;minio&lt;/a&gt;, which is the theme I still use today. It uses &lt;code&gt;Sass&lt;/code&gt; instead of pure &lt;code&gt;CSS&lt;/code&gt;, and its sources are neatly organized. Plus, it comes with a nicely configured toolchain, which allows to get feedback on changes made to the theme instantly.&lt;/p&gt;
&lt;h2 id=&#34;source-organization&#34;&gt;Source organization&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#source-organization&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Each blog post has its own markdon file, numbered chronologically:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0001-hello-world.md
0002-i-use-vim-and-so-should-you.md
0003-finding-a-good-project-name.md
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I like this scheme because posts are naturally sorted by time, and because I know immediately know how much articles I&amp;rsquo;ve written. (More than 100 today!)&lt;/p&gt;
&lt;p&gt;Since I don&amp;rsquo;t really want the internal number to be seen outside, all the articles have a &lt;code&gt;slug&lt;/code&gt; in the &amp;ldquo;front matter&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;font-weight:bold&#34;&gt;# In 0042-foo.md
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fff;font-weight:bold&#34;&gt;&lt;/span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;slug: &amp;#34;foo&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;date: &amp;#34;2016-03-31T13:00:19+00:00&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;draft: false
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;title: &amp;#34;...&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means the &lt;code&gt;0042-foo.md&lt;/code&gt; file will get written as &lt;code&gt;foo/index.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I also told &lt;code&gt;nginx&lt;/code&gt; that &lt;code&gt;blog/post/foo&lt;/code&gt; correspond to &lt;code&gt;blog/post/foo/index.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;/blog&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;try_files&lt;/span&gt; &lt;span style=&#34;color:#40ffff&#34;&gt;$uri&lt;/span&gt; &lt;span style=&#34;color:#40ffff&#34;&gt;$uri/index.html&lt;/span&gt; =&lt;span style=&#34;color:#3677a9&#34;&gt;404&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is called &lt;em&gt;pretty URLs&lt;/em&gt; in Hugo&amp;rsquo;s documentation.&lt;/p&gt;
&lt;h2 id=&#34;comments&#34;&gt;Comments&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#comments&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The last piece of the puzzle is the comments system.&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&#34;https://posativ.org/isso/&#34;&gt;isso&lt;/a&gt;, a self-hosted comment service.&lt;/p&gt;
&lt;p&gt;First, I&amp;rsquo;ve patched the Hugo template to add a tiny bit of JavaScript at the bottom of every article:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&amp;lt;!-- in layouts/entry.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;data-isso&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;//dmerej.info/isso/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#bbb&#34;&gt;src&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;//dmerej.info/isso/js/embed.min.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;section&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;isso-thread&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;section&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I made sure the &lt;code&gt;isso&lt;/code&gt; service was reachable at &lt;code&gt;https://dmerej.info/isso&lt;/code&gt;, with help from &lt;code&gt;nginx&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# In /etc/nginx/conf.d/blog.conf
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;location&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;/isso&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;X-Forwarded-For&lt;/span&gt; &lt;span style=&#34;color:#40ffff&#34;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;X-Script-Name&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;/isso&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;Host&lt;/span&gt; &lt;span style=&#34;color:#40ffff&#34;&gt;$host&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;proxy_set_header&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span style=&#34;color:#40ffff&#34;&gt;$scheme&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;proxy_pass&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;http://localhost:1234&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and &lt;code&gt;systemd&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# In isso.service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[Unit]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;Description&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;isso comments service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;Wants&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;network-online.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;After&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;network-online.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[Service]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;Type&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;simple&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;ExecStart&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;/srv/isso/.local/bin/isso -c /srv/isso/isso.conf run&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;User&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;isso&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[Install]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;WantedBy&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;multi-user.target&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The comment form does not show if the visitor has disabled JavaScript. I find that a bit sad, but on the other hand it keeps robots from posting spam (at least so far).&lt;/li&gt;
&lt;li&gt;All the comments are stored in a SQLite database. I have a systemd timer to back it up every day.&lt;/li&gt;
&lt;li&gt;People can opt-in to leave their e-mail in the form. Isso does nothing with it but store them in its database. I sometimes use them to send them private messages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that&amp;rsquo;s how the blog works under the hood! Stay tuned for &lt;a href=&#34;https://dmerej.info/blog/post/my-blogging-flow-part-2-publishing/&#34;&gt;part 2&lt;/a&gt;, where I&amp;rsquo;ll explain how new articles get written and published.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I&amp;rsquo;m using unicode character &lt;small&gt;RIGHT ANGLE BRACKET&lt;/small&gt; to prevent Hugo from expanding the shortcode in &lt;em&gt;this&lt;/em&gt; article &amp;hellip;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Killing unwrap()</title>
      <link>https://dmerej.info/blog/post/killing-unwrap/</link>
      <pubDate>Wed, 30 Jan 2019 19:11:26 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/killing-unwrap/</guid>
      <description>&lt;h1 id=&#34;wait-what-who-do-you-want-to-kill&#34;&gt;Wait, what? Who do you want to kill?&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#wait-what-who-do-you-want-to-kill&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;In Rust, to indicate errors or absence of a value we use types named &lt;code&gt;Result&lt;/code&gt; and &lt;code&gt;Option&lt;/code&gt; respectively.&lt;/p&gt;
&lt;p&gt;If we need the &lt;em&gt;value&lt;/em&gt; of an Result or Option, we can write code like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;maybe_bar&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;get_bar();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// bar is now an Option&amp;lt;String&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;maybe_bar.is_some()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar.unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// now bar is a String
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// handle the absence of bar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works well but there&amp;rsquo;s a problem: if after some refactoring the &lt;code&gt;if&lt;/code&gt; statement is not called, the entire program will crash with: &lt;code&gt;called Option::unwrap on a None value&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is fine if &lt;code&gt;unwrap()&lt;/code&gt; is called in a test, but in production code it&amp;rsquo;s best to prevent panics altogether.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s the why. Let&amp;rsquo;s see the how.&lt;/p&gt;
&lt;h1 id=&#34;example-1---handling-options&#34;&gt;Example 1 - Handling options&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#example-1---handling-options&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s go back to our first example: we&amp;rsquo;ll assume there is a &lt;code&gt;bar::return_opt()&lt;/code&gt; function coming from an external crate and returning an &lt;code&gt;Option&amp;lt;Bar&amp;gt;&lt;/code&gt;, and that we are calling it in &lt;code&gt;my_func&lt;/code&gt;, a function also returning an option:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;Foo&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_opt();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.is_none()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;None&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// doing something with `value` here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So how do we get rid of the &lt;code&gt;unwrap()&lt;/code&gt; here? Simple, with the &lt;em&gt;question mark operator&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;Foo&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_opt()?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Done: the question mark will cause the function to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// return None automatically if bar::return_opt() is None
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// We can use `value` here directly!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If &lt;code&gt;my_func()&lt;/code&gt; does not return an &lt;code&gt;Option&lt;/code&gt; or a &lt;code&gt;Result&lt;/code&gt; you cannot
use this technique, but a &lt;code&gt;match&lt;/code&gt; may be used to keep the &amp;ldquo;early return&amp;rdquo;
pattern:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;SomeType&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_opt()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;None&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;SomeType::default()&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(v)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;v&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// do something with v
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note the how the &lt;code&gt;match&lt;/code&gt; expression and the &lt;code&gt;let&lt;/code&gt; statement are combined. Yay Rust!&lt;/p&gt;
&lt;h1 id=&#34;example-2---handling-result&#34;&gt;Example 2 - Handling Result&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#example-2---handling-result&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s see the bad code first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;Foo,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_res();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res.is_err()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Err&lt;/span&gt;(MyError::new(res.unwrap_err());&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res.unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here the &lt;code&gt;bar::return_res()&lt;/code&gt; function returns a &lt;code&gt;Result&amp;lt;BarError, Bar&amp;gt;&lt;/code&gt; (where
&lt;code&gt;BarError&lt;/code&gt; and &lt;code&gt;Bar&lt;/code&gt; are defined in an external crate). The &lt;code&gt;MyError&lt;/code&gt; type is in the current crate.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know about you, but I really hate the 4th line: &lt;code&gt;return Err(MyError::new(res.unwrap_err());&lt;/code&gt; What a mouthful!&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see some ways to rewrite it.&lt;/p&gt;
&lt;h2 id=&#34;using-from&#34;&gt;Using From&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-from&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One solution is to use the question mark operator anyway:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;Foo,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Error&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_res()?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code won&amp;rsquo;t compile of course, but the compiler will &lt;a href=&#34;https://dmerej.info/blog/post/letting-the-compiler-tell-you-what-to-do/&#34;&gt;tell you what to do&lt;/a&gt;,
and you&amp;rsquo;ll just need to implement the &lt;code&gt;From&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;From&lt;/span&gt;&amp;lt;BarError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;from&lt;/span&gt;(error: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;BarError&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;MyError&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Error::new(&amp;amp;format!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bar error: &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;error))&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works fine unless you need to add some context (for instance, you may have an &lt;code&gt;IOError&lt;/code&gt; but not the name of the file that caused it).&lt;/p&gt;
&lt;h2 id=&#34;using-map_err&#34;&gt;Using map_err&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-map_err&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;code&gt;map_err&lt;/code&gt; in action:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;Foo,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Error&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_res():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;some_context&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;....;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res.map_err(|e|&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError::new(e,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;some_context))?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can still use the question mark operator, the ugly &lt;code&gt;Err(MyError::new(...))&lt;/code&gt;
is gone, and we can provide some additional context in our custom Error type. Epic win!&lt;/p&gt;
&lt;h1 id=&#34;example-3---converting-from-option&#34;&gt;Example 3 - Converting from Option&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#example-3---converting-from-option&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This time we are calling a function that returns an &lt;code&gt;Option&lt;/code&gt; and we want a &lt;code&gt;Result&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Again, let&amp;rsquo;s start with the &amp;ldquo;bad&amp;rdquo; version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;Foo,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_opt();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res.is_none()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Err&lt;/span&gt;(MyError::new(....));&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;res.unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The solution is to use &lt;code&gt;ok_or_else&lt;/code&gt;, a bit like how we used the &lt;code&gt;unwrap_err&lt;/code&gt; before:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;Foo,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;value&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_opt().ok_or_else(||&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;(MyError::new(...))?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;example-4---converting-to-option&#34;&gt;Example 4 - Converting to Option&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#example-4---converting-to-option&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This time we want to discard the error and simply return None.&lt;/p&gt;
&lt;p&gt;Bad example (even with the pattern matching):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;SomeType&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;result&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_res();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;v&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;(result)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;     &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Err&lt;/span&gt;(_)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;None&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;     &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(v)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;v&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(v)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Better example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;my_func&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;SomeType&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;v&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;bar::return_res().ok()?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Some&lt;/span&gt;(v)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;example-5---assertions&#34;&gt;Example 5 - Assertions&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#example-5---assertions&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Sometime you may want to catch errors that are a consequence of faulty logic within the code.&lt;/p&gt;
&lt;p&gt;For instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;mystring&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;format!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;spam,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;eggs);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ... some code here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;index&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;mystring.find(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;:&amp;#39;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ve built an immutable string with &lt;code&gt;format()&lt;/code&gt; and we put a colon in the format string. There&amp;rsquo;s no way for the string to &lt;em&gt;not&lt;/em&gt; contain a colon in the last line, and so we &lt;em&gt;know&lt;/em&gt; that &lt;code&gt;find&lt;/code&gt; will return something.&lt;/p&gt;
&lt;p&gt;I reckon we should still kill the &lt;code&gt;unwrap()&lt;/code&gt; here and make the error message clearer with &lt;code&gt;expect()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;index&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;mystring.find(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;:&amp;#39;&lt;/span&gt;).expect(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;my_string should contain a colon&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;in-tests-and-main&#34;&gt;In tests and main&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#in-tests-and-main&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Note: I&amp;rsquo;d like to thank Jeikabu whose &lt;a href=&#34;https://dev.to/jeikabu/comment/8kb4&#34;&gt;comment on dev.to&lt;/a&gt; triggered the addition of this section&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take another example. Here is the code under test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Foo&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;};&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;setup_foo&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;Foo,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Error&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;frob_foo&lt;/span&gt;(foo: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Foo&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;(),&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Error&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Traditionally, you had to write tests for &lt;code&gt;setup_foo()&lt;/code&gt; and &lt;code&gt;frob_foo()&lt;/code&gt; this way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[test]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_foo&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;foo&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;setup_foo().unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;frob_foo(foo).unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But since recent versions of Rust you can write the same test this way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[test]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_foo&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;(),&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;foo&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;setup_foo()?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;frob_foo(foo)&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another big win in legibility, don&amp;rsquo;t you agree?&lt;/p&gt;
&lt;p&gt;By the way, the same technique can be used with the &lt;code&gt;main()&lt;/code&gt; function (the entry point for Rust executables):&lt;/p&gt;
&lt;p&gt;Old version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;result&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;setup_foo().unwrap();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;New version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;(),&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;MyError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;foo&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;setup_foo()?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;...&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;closing-thoughts&#34;&gt;Closing thoughts&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#closing-thoughts&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When using &lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt; types in your own code, take some time to read
(and re-read) the documentation. Rust standard library gives you many ways to
solve the task at hand, and sometimes you&amp;rsquo;ll find a function that does exactly
what you need, leading to shorter, cleaner and more idiomatic Rust code.&lt;/p&gt;
&lt;p&gt;If you come up with better solutions or other examples, please let me know!
Until then, happy Rusting :)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Letting the compiler tell you what to do - an example using Rust</title>
      <link>https://dmerej.info/blog/post/letting-the-compiler-tell-you-what-to-do/</link>
      <pubDate>Sat, 12 Jan 2019 12:26:27 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/letting-the-compiler-tell-you-what-to-do/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;ve ever written code in a compiled language (C, C++, Java, &amp;hellip;), you are probably used to compiler error messages, and you may think there are only here to prevent you from making mistakes.&lt;/p&gt;
&lt;p&gt;Well, sometimes you can also use compiler error messages to &lt;em&gt;design and implement new features&lt;/em&gt;. Let me show you with a simple command-line program written in Rust.&lt;/p&gt;
&lt;h1 id=&#34;an-example&#34;&gt;An example&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#an-example&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s the code we have written so far:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;structopt::StructOpt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug, StructOpt)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Opt&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(long = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--dry-run&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;dry_run: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Opt::from_args();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dry_run&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.dry_run;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;println!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;dry run: &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dry_run);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We implemented a &lt;code&gt;--dry-run&lt;/code&gt; option using the &lt;a href=&#34;https://github.com/TeXitoi/structopt&#34;&gt;structopt crate&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now we want to add a &lt;code&gt;--color&lt;/code&gt; option that can have the following values: &lt;code&gt;never&lt;/code&gt;, &lt;code&gt;always&lt;/code&gt;, and &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But structopt (nor clap, which it is based on) does &lt;em&gt;not&lt;/em&gt; have the concept of &amp;ldquo;choice&amp;rdquo;, like &lt;code&gt;argparse&lt;/code&gt; or &lt;code&gt;docopt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So we &lt;em&gt;pretend&lt;/em&gt; it does and we write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ColorWhen&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;Always,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;Never,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;Auto,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug, StructOpt)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Opt&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(long = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--dry-run&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;dry_run: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;        long = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--color&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;        help = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Whether to enable colorful output.&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;    )]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;color_when: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ColorWhen&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Opt::from_args();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dry_run&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.dry_run;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.color_when;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;println!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;dry run: &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dry_run);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;println!(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;color: &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Note: this is sometimes called &amp;ldquo;programming by wishful thinking&amp;rdquo; and can be used in various situations&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, we try and compile this code and are faced with a bunch of compiler errors.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s where the magic starts. We are going to make this work &lt;em&gt;without&lt;/em&gt; opening structopt&amp;rsquo;s documentation and by &lt;em&gt;only&lt;/em&gt; following the advice given by the compiler, one error after the other. Ready? Let&amp;rsquo;s go!&lt;/p&gt;
&lt;h2 id=&#34;error-1&#34;&gt;Error 1&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#error-1&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;color_when: ColorWhen,
   |     ^^^^^^^^^^^^^^^^^^^^^ `ColorWhen` cannot be formatted using `{:?}`
   |
   = help: the trait `std::fmt::Debug` is not implemented for `ColorWhen`
   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We do what we are told, and add the &lt;code&gt;#[derive(Debug)]&lt;/code&gt; annotation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ColorWhen&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, that what easy. Let&amp;rsquo;s move on to the next error.&lt;/p&gt;
&lt;h2 id=&#34;error-2&#34;&gt;Error 2&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#error-2&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  | #[derive(StructOpt)]
  |          ^^^^^^^^^ the trait `std::str::FromStr` is not implemented for
  |                    `ColorWhen`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler tells us it does not know how to convert the command line argument (a string) into the enum.&lt;/p&gt;
&lt;p&gt;We don&amp;rsquo;t really remember what the &lt;code&gt;FromStr&lt;/code&gt; trait contains. We could look up the documentation (but that would be cheating), so instead we write an empty implementation and see what happens:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;::FromStr&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;ColorWhen&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;error-3&#34;&gt;Error 3&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#error-3&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Again, the compiler tells us what to do:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;not all trait items implemented, missing: `Err`, `from_str`
  --&amp;gt; src/main.rs:10:1
   |
10 | impl std::str::FromStr for ColorWhen {}

missing `Err`, `from_str` in implementation
note: `Err` from trait: `type Err;`
note: `from_str` from trait:
  `fn(&amp;amp;str) -&amp;gt; std::result::Result&amp;lt;Self, &amp;lt;Self as std::str::FromStr&amp;gt;::Err&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We need an &lt;a href=&#34;https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types&#34;&gt;associated type&lt;/a&gt; &lt;code&gt;Err&lt;/code&gt;, and a &lt;code&gt;from_str()&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with the Err type. We&amp;rsquo;ll need to tell the user about the invalid &lt;code&gt;--color&lt;/code&gt; option, so let&amp;rsquo;s use an enum with a &lt;code&gt;InvalidArgs&lt;/code&gt; struct containing a description:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;FooError&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;InvalidArgs&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;details: &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt; },&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how the compiler almost &amp;ldquo;forced&amp;rdquo; us to have our own error type, which is a very good practice!&lt;/p&gt;
&lt;p&gt;Anyway, along with the &lt;code&gt;from_str&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;::FromStr&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;ColorWhen&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;Err&lt;/span&gt; =&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;FooError;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;from_str&lt;/span&gt;(s: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;ColorWhen,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;FooError&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;s&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;always&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(ColorWhen::Always),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;auto&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(ColorWhen::Auto),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;never&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(ColorWhen::Never),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;_&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;details&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Choose between &amp;#39;never&amp;#39;, &amp;#39;always&amp;#39;, &amp;#39;auto&amp;#39;&amp;#34;&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Err&lt;/span&gt;(FooError::InvalidArgs&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;details: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;details&lt;/span&gt;.to_string()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;})&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;error-4&#34;&gt;Error 4&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#error-4&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error[E0599]: no method named `to_string` found
  for type `FooError` in the current scope
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All custom error types should be convertible to strings, so let&amp;rsquo;s implement  that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::string::&lt;span style=&#34;color:#24909d&#34;&gt;ToString&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;FooError&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;to_string&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;String&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;FooError::InvalidArgs&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;details&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;details.to_string(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It compiles!&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s check error handling:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-test&#34; data-lang=&#34;test&#34;&gt;$ cargo run -- --color foobar
error: Invalid value for &amp;#39;--color &amp;lt;color_when&amp;gt;&amp;#39;:
  Choose between &amp;#39;never&amp;#39;, &amp;#39;always&amp;#39;, &amp;#39;auto&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s check with a valid choice:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo run -- --color never
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dry run: &lt;span style=&#34;color:#24909d&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;color: Never
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It works!&lt;/p&gt;
&lt;h2 id=&#34;the-default&#34;&gt;The default&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-default&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s still a small problem: we did not use a &lt;code&gt;Option&lt;/code&gt; for the &lt;code&gt;color_when&lt;/code&gt; field, so the &lt;code&gt;--color&lt;/code&gt;
command line flag is actually required:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: The following required arguments were not provided:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --color &amp;lt;color_when&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Can&amp;rsquo;t blame Rust there. That&amp;rsquo;s our fault for not having used an optional ColorWhen field in the first place.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try and fix that by using an &lt;code&gt;Option&amp;lt;&amp;gt;&lt;/code&gt; instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Opt&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;        long = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--color&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;        help = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Whether to enable colorful output&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;    )]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;color_when: &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;ColorWhen&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, since we did not do anything with the &lt;code&gt;opt.color_when&lt;/code&gt; but print it, everything still works :)&lt;/p&gt;
&lt;h2 id=&#34;error-5&#34;&gt;Error 5&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#error-5&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Had we tried to use the option directly like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;force_no_color&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.color_when;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;ColorWhen::Never&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;force_no_color(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ..
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The compiler would have told us about our mistake:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ColorWhen::Never =&amp;gt; force_no_color(),
^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found enum `ColorWhen`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And we would have been forced to handle the default value, for instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when.unwrap_or(ColorWhen::Auto);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;side-note&#34;&gt;Side note&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#side-note&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s an other cool trick we can use to achieve the same result, by leveraging the &lt;code&gt;default&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ColorWhen&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;Always,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;Never,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;Auto,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;std::default::&lt;span style=&#34;color:#24909d&#34;&gt;Default&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;ColorWhen&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;default&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Self&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;ColorWhen::Auto&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And calling &lt;code&gt;unwrap_or_default()&lt;/code&gt; instead of &lt;code&gt;unwrap_or()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;color_when&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt.color_when.unwrap_or_default();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code is a bit longer but I find it more readable and more &amp;ldquo;intention revealing&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;(End of side note)&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I hope this gave you new insights about what a good compiler can do, or at least a feel of what writing Rust looks like.&lt;/p&gt;
&lt;p&gt;I call this new workflow &amp;ldquo;compiler-driven development&amp;rdquo; and I find it nicely complements other well-known workflows like TDD.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Final note: to be honest we could have achieved better results by reading the documentation too: for instance, we could have used a &lt;a href=&#34;https://docs.rs/structopt/0.2.14/structopt/#custom-string-parsers&#34;&gt;custom string parser&lt;/a&gt; instead of the &lt;code&gt;FromStr&lt;/code&gt; boilerplate, and implemented the Display trait on our &lt;a href=&#34;https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/define_error_type.html&#34;&gt;custom error&lt;/a&gt; instead. Good docs matter too &amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I am writing a book about CI</title>
      <link>https://dmerej.info/blog/post/im-writing-a-book/</link>
      <pubDate>Fri, 11 Jan 2019 10:58:18 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/im-writing-a-book/</guid>
      <description>&lt;h1 id=&#34;why&#34;&gt;Why?&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#why&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I wanted to talk about CI for a very long time (more than 2 years). But it&amp;rsquo;s a huge topic, and it took me some time before I decided to &lt;a href=&#34;https://dmerej.info/blog/post/introducing-tips-from-a-build-farmer/&#34;&gt;start a blog post series &lt;/a&gt; about it.&lt;/p&gt;
&lt;p&gt;But then I realized that was the wrong format: you see, writing and publishing one post at a time requires for you to know exactly what to say and in what order, and I found that was not the case for the &amp;ldquo;Tips From A Build Farmer&amp;rdquo; series. So instead, I am going to try and write the whole thing as a book.&lt;/p&gt;
&lt;h1 id=&#34;how&#34;&gt;How?&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#how&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For now, I am only focusing on the &lt;em&gt;content&lt;/em&gt;: I just have a bunch of Markdown files I can turn into a big pdf thanks to &lt;a href=&#34;https://pandoc.org/&#34;&gt;pandoc&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once done, I will probably publish the pdf and the sources on the Internet, available for free.&lt;/p&gt;
&lt;h1 id=&#34;when&#34;&gt;When?&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#when&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I have no clue at all, this is my first attempt at writing a book! But I will surely post updates there on the blog &amp;ndash; wish me luck!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A definition of the Linux desktop</title>
      <link>https://dmerej.info/blog/post/a-definition-of-the-linux-desktop/</link>
      <pubDate>Wed, 02 Jan 2019 09:56:30 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/a-definition-of-the-linux-desktop/</guid>
      <description>&lt;p&gt;Quite some time ago, I came across a thread from Gary Bernhardt on twitter.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what he had to say about Linux, compared to macOS and Windows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unlike the other two operating systems, you have control. But nothing will ever
work reliably, especially across upgrades. When it breaks, the community will
frame it as your own moral failure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a guy who uses Linux for almost everything (both at work and at home), you may think I would disagree.&lt;/p&gt;
&lt;p&gt;But no, I agree with almost everything, except I would rephrase the last sentence. Let me explain.&lt;/p&gt;
&lt;h1 id=&#34;control&#34;&gt;Control&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#control&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s start at the beginning. What kind of control do you have depending on the operating system you use?&lt;/p&gt;
&lt;h2 id=&#34;control-on-macos&#34;&gt;Control on macOS&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#control-on-macos&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You have almost no control over hardware. You buy hardware that is manufactured by Apple, often in an &amp;ldquo;Apple store&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Most applications have minimal configuration, simple things like preventing the laptop to suspend when closing the lid are hard to achieve &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Finally, you often haven little control over &lt;em&gt;your own data&lt;/em&gt;. Watching the movie you bought on iTunes on an non-Apple device is very hard.&lt;/p&gt;
&lt;p&gt;You can put all your stuff on iTunes or iCloud, but if you loose access to your account you lose everything. &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;control-on-windows&#34;&gt;Control on Windows&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#control-on-windows&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Compared to macOS, you have more control over hardware. For instance, you can buy a new battery when the one you use is failing instead of buying a completely new device.&lt;/p&gt;
&lt;p&gt;But still, you get less and less control over what to update and when, and let&amp;rsquo;s not talk about privacy&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;control-on-linux&#34;&gt;Control on Linux&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#control-on-linux&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You control (almost) everything.&lt;/p&gt;
&lt;p&gt;You can choose your distribution. You can choose its stability. For instance on Debian, you can choose between &lt;em&gt;stable&lt;/em&gt;, &lt;em&gt;testing&lt;/em&gt;, or &lt;em&gt;unstable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You can chose your desktop environment: KDE, Gnome, LXDE, XFCE, Mint, or even use no desktop environment at all.&lt;/p&gt;
&lt;p&gt;You can can choose your window manager, your init system, your package manager &amp;hellip;&lt;/p&gt;
&lt;p&gt;You can choose when and what to update (less so on &amp;ldquo;rolling distributions&amp;rdquo; like Arch Linux, although it is still possible with extra care &amp;hellip;), etc.&lt;/p&gt;
&lt;p&gt;Control is everywhere and so ubiquitous it&amp;rsquo;s even scary. But it&amp;rsquo;s free: nothing prevents you from experimenting but time and energy.&lt;/p&gt;
&lt;h1 id=&#34;when-it-breaks&#34;&gt;When it breaks&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#when-it-breaks&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s talk about what happen when software you are using breaks.&lt;/p&gt;
&lt;p&gt;On macOS and Windows, all you can do is pray and find someone who has a solution. There are bug trackers of course (but on macOS you can only see the bugs &lt;em&gt;you&lt;/em&gt; opened).&lt;/p&gt;
&lt;p&gt;If you upgrade Windows and a third-party driver stops working, you&amp;rsquo;re basically screwed. I&amp;rsquo;ve seen my Mom loose access to its scanner for a few months because of this.&lt;/p&gt;
&lt;p&gt;On Linux, things &lt;em&gt;will&lt;/em&gt; break more often. They are less people to do QA, there are more unknowns, tons of different configurations (as we saw in the &amp;ldquo;control&amp;rdquo; section), and a pressure to release often and stay &amp;ldquo;bleeding edge&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Almost everything is written and maintained by non-paid volunteers (and they do a terrific job by the way).&lt;/p&gt;
&lt;p&gt;Upgrades are big and scary, and so things often break. No point discussing that.&lt;/p&gt;
&lt;p&gt;A few months ago, after I upgraded Arch Linux on my laptop, the brightness control button ceased to work and I have no clue why.&lt;/p&gt;
&lt;p&gt;But to be honest, I did not take the time to look for a solution, which leads us to the next section.&lt;/p&gt;
&lt;h1 id=&#34;your-own-moral-failure&#34;&gt;Your own moral failure&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#your-own-moral-failure&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at some exchanges between an average user with a problem, looking for answer from the community, for instance in a public bug tracker or a forum:&lt;/p&gt;
&lt;p&gt;First example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt; Q: I&amp;#39;ve upgraded *foo* to version 3.0 and now I cannot frob anymore
&amp;gt; A: Did you read the changelog before upgrading?
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Second example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt; Q: I bought a new printer and now I can only print in black and white!
&amp;gt; A: Did you research compatibility with Linux before buying the new printer?
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s try to put ourselves in the shoes of those users. They might think they failed at something, or even that they are not even supposed to ask this kind of question&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, which illustrates with the &amp;ldquo;moral failure&amp;rdquo; Gary talked about.&lt;/p&gt;
&lt;h1 id=&#34;rephrasing-the-last-part&#34;&gt;Rephrasing the last part&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#rephrasing-the-last-part&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So where do I disagree? Well, it&amp;rsquo;s the &amp;ldquo;framing&amp;rdquo; part I don&amp;rsquo;t like. I would rephrase the last sentence as: &amp;ldquo;When it breaks, it will be your (or the community&amp;rsquo;s) responsibility to fix it&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Let me elaborate.&lt;/p&gt;
&lt;p&gt;When stuff on Linux breaks, you &lt;em&gt;can&lt;/em&gt; do something about it.&lt;/p&gt;
&lt;p&gt;You can downgrade, you can switch to an other distribution, you can discuss the problem on a forum, you can send e-mails to mailing list, you can open an issue on the bug tracker.&lt;/p&gt;
&lt;p&gt;You can even get the code and patch it yourself if you are not afraid. Sometimes it&amp;rsquo;s not that hard.&lt;/p&gt;
&lt;p&gt;So I don&amp;rsquo;t think the community is &lt;em&gt;framing&lt;/em&gt; it. I just think it&amp;rsquo;s how things work in the Linux world. You just can&amp;rsquo;t expect volunteers to always fix all the bugs for free. And you can&amp;rsquo;t expect the same level of quality as when QA is done by paid professionals.&lt;/p&gt;
&lt;p&gt;So, yes, in exchange for the freedom of control you get some duties. Your duty is to help yourself and others when things break. And by the way, teaching users about reading changelogs and doing research before buying hardware is good advice, &lt;em&gt;if&lt;/em&gt; they are willing to accept it.&lt;/p&gt;
&lt;p&gt;For me those duties are a small price to pay because I value control and freedom more than convenience. If you are willing to accept those duties to gain this freedom and are not using Linux, give it a go!&lt;/p&gt;
&lt;p&gt;If you are using Linux and want to &amp;ldquo;convert&amp;rdquo; other people, (like friends or family), explain this to them so they don&amp;rsquo;t get mad at you. Be ready to help them for things they don&amp;rsquo;t understand. You can even teach them a few things, or teach them how to learn. That&amp;rsquo;s how I got to use Linux in the first place almost 15 years ago.&lt;/p&gt;
&lt;p&gt;And if you don&amp;rsquo;t want to try and fix stuff when it breaks, keep using macOS or Windows. There&amp;rsquo;s nothing wrong with that.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I spent a day looking for a solution, then decided I did not really needed it. But if you know how to do it, please let met know :)&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Ask &lt;a href=&#34;https://duckduckgo.com/?q=itunes+update+data+loss&amp;amp;t=h_&amp;amp;ia=web&#34;&gt;duckduckgo&lt;/a&gt; if you think it&amp;rsquo;s a rare problem &amp;hellip;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;This is not hypothetical. I&amp;rsquo;ve talked about that in an article called &lt;a href=&#34;https://dmerej.info/blog/post/why-i-love-arch-linux/&#34;&gt;&amp;ldquo;Why I love Arch Linux&amp;rdquo;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>ruplacer: find and replace text in source files</title>
      <link>https://dmerej.info/blog/post/ruplacer/</link>
      <pubDate>Sun, 14 Oct 2018 12:34:43 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/ruplacer/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Today I&amp;rsquo;d like to talk about a command-line tool I&amp;rsquo;ve been working on.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s called &lt;a href=&#34;https://github.com/dmerejkowsky/ruplacer&#34;&gt;ruplacer&lt;/a&gt; and as the name suggest, it&amp;rsquo;s &lt;em&gt;rually&lt;/em&gt; cool and written in Rust.&lt;/p&gt;
&lt;p&gt;Basically, it finds and replaces text in source files. Here&amp;rsquo;s a screenshot of ruplacer in action:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/ruplacer.png&#34; alt=&#34;ruplacer screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;Some nice features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Skips files listed in &lt;code&gt;.gitignore&lt;/code&gt;, as well as binary files&lt;/li&gt;
&lt;li&gt;Runs in dry run mode by default (use &lt;code&gt;--go&lt;/code&gt; to actually write the changes to the filesystem)&lt;/li&gt;
&lt;li&gt;Defaults to searching the current working directory, although an other path maybe specified after the pattern and the replacement.&lt;/li&gt;
&lt;li&gt;Uses Rust regular expressions, which means you can capture groups in the pattern and use them in the replacement. For instance:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Replaces dates looking like DD/MM/YYYY to YYYY-MM-DD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ruplacer &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;(\d{2})/(\d{2})/(\d{4})&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;$3-$1-$2&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Can be run with &lt;code&gt;--no-regex&lt;/code&gt; if the pattern is just a substring and should not be used as a regular expression&lt;/li&gt;
&lt;li&gt;Last, but not least  there&amp;rsquo;s also a &lt;code&gt;--subvert&lt;/code&gt; mode, which allows you to perform replacements on a variety of case styles:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ruplacer --subvert foo_bar spam_eggs
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Patching src/foo.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-- foo_bar, FooBar, and FOO_BAR!
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;++ spam_eggs, SpamEggs, and SPAM_EGGS!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;how-it-works&#34;&gt;How it works&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#how-it-works&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s how it works:&lt;/p&gt;
&lt;p&gt;First, we build a &lt;a href=&#34;https://crates.io/crates/structopt&#34;&gt;structopt&lt;/a&gt; struct for the command-line arguments parsing. Depending on the presence of the &lt;code&gt;--subvert&lt;/code&gt; or &lt;code&gt;--no-rexeg&lt;/code&gt; flags, we  build a &lt;em&gt;Query&lt;/em&gt;, which can be of several types: &lt;code&gt;Substring&lt;/code&gt;, &lt;code&gt;Regex&lt;/code&gt; or &lt;code&gt;Subvert&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then we leverage the &lt;a href=&#34;https://crates.io/crates/ignore&#34;&gt;ignore&lt;/a&gt; crate to walk through every file in the source directory  while skipping files listed in &lt;code&gt;.gitignore&lt;/code&gt;. By the way, the ignore crates comes directly from &lt;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&gt;ripgrep&lt;/a&gt;, an awesome alternative to &lt;code&gt;grep&lt;/code&gt; also written in Rust.&lt;/p&gt;
&lt;p&gt;Along the way, we build a &lt;em&gt;FilePatcher&lt;/em&gt; from the source file and the query. The FilePatcher goes through every line of the file and  then sends it along with the query to  a &lt;em&gt;LinePatcher&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The LinePatcher runs the code corresponding to the query type and returns a new string, using the &lt;a href=&#34;https://crates.io/crates/Inflector&#34;&gt;Inflector&lt;/a&gt; crate to perform case string conversions if required.&lt;/p&gt;
&lt;p&gt;Finally, if the string has changed, the FilePatcher builds a &lt;em&gt;Replacement&lt;/em&gt; struct and pretty-prints it to the user. While doing so, it also keeps a record of the modified contents of the file. Finally, if not in dry-run mode, it overwrites the file with the new contents.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s pretty much it :)&lt;/p&gt;
&lt;h1 id=&#34;why-im-sharing-this&#34;&gt;Why I&amp;rsquo;m sharing this&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#why-im-sharing-this&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The idea of ruplacer started almost a decade ago when a colleague of mine showed me a shell function called &lt;code&gt;replacer&lt;/code&gt; (thanks, Cédric!) It was basically a mixture of calls to &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt; and &lt;code&gt;diff&lt;/code&gt;. You can still &lt;a href=&#34;https://github.com/cgestes/ctafconf/blob/78b92a60bc185b73f95418e3e913e33aae8799f6/bin/replacer#L75&#34;&gt;find it online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because I wanted better cross-platform support, a dry-run mode and a colorful output, I &lt;a href=&#34;https://github.com/dmerejkowsky/replacer&#34;&gt;rewrote it in Python&lt;/a&gt; a few years ago. Along the way, the features, command line syntax and the style of the output changed quite a lot, but I&amp;rsquo;ve been using it regularly for all this time.&lt;/p&gt;
&lt;p&gt;Finally, after hearing about ripgrep and &lt;a href=&#34;https://github.com/sharkdp/fd&#34;&gt;fd&lt;/a&gt;, I decided to give Rust a go, and that&amp;rsquo;s how ruplacer, the third incarnation of this tool, was born. This makes me confident it&amp;rsquo;s good enough for &lt;em&gt;you&lt;/em&gt; to try.&lt;/p&gt;
&lt;p&gt;If you have &lt;code&gt;cargo&lt;/code&gt; installed, you can get ruplacer by running &lt;code&gt;cargo install ruplacer&lt;/code&gt;. Otherwise, you will find the &lt;a href=&#34;https://github.com/dmerejkowsky/ruplacer/tree/master/src&#34;&gt;source code&lt;/a&gt; and &lt;a href=&#34;https://github.com/dmerejkowsky/ruplacer/releases&#34;&gt;pre-compiled binaries&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Syntax Highlighting Is Useless</title>
      <link>https://dmerej.info/blog/post/syntax-highlighting-is-useless/</link>
      <pubDate>Thu, 04 Oct 2018 13:30:31 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/syntax-highlighting-is-useless/</guid>
      <description>&lt;p&gt;… at least when it comes to Markdown files ;)&lt;/p&gt;
&lt;h1 id=&#34;introduction-editing-this-blog-in-neovim&#34;&gt;Introduction: editing this blog in Neovim&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction-editing-this-blog-in-neovim&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s what it used to look like to edit one of my articles in Neovim:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/markdown-colored.png&#34; alt=&#34;Colored markdown file in Neovim&#34;&gt;&lt;/p&gt;
&lt;p&gt;Take a quick look. Do you see what&amp;rsquo;s wrong?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, the line about the &lt;code&gt;summary&lt;/code&gt; in the front matter is colored in green. The front matter uses YAML syntax, but Neovim does not know it and thus highlights this line incorrectly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Second, the python code is OK, but the language name is misspelt: &lt;code&gt;pyton&lt;/code&gt; instead of &lt;code&gt;python&lt;/code&gt;. I &lt;em&gt;am&lt;/em&gt; using Neovim&amp;rsquo;s built-in spell checker, but since Neovim &amp;ldquo;knows&amp;rdquo; the stuff after &lt;code&gt;```&lt;/code&gt; is source code, it disables spell checking for this part of the text.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Third, the link to &amp;lsquo;Using CMake and Ninja&amp;rsquo; is built using &lt;a href=&#34;https://gohugo.io/functions/ref/&#34;&gt;hugo syntax&lt;/a&gt;, and if you were extra careful you may have noticed that the path to the article after &lt;code&gt;ref&lt;/code&gt; starts with a double quote (&lt;code&gt;&amp;quot;&lt;/code&gt;), but ends with a single quote (&lt;code&gt;&#39;&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;turning-syntax-highlighting-off&#34;&gt;Turning syntax highlighting off&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#turning-syntax-highlighting-off&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For quite some time I did not think to much about this situation, until I read &lt;em&gt;&lt;a href=&#34;http://www.linusakesson.net/programming/syntaxhighlighting/&#34;&gt;A case against syntax highlighting&lt;/a&gt;&lt;/em&gt;, by Linus Åkesson.&lt;/p&gt;
&lt;p&gt;So one day I decided to try and turn the syntax highlighting off:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/markdown-plain.png&#34; alt=&#34;Un-colored markdown file&#34;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This time, the spell checker checks &lt;em&gt;everything&lt;/em&gt;, and the typo in &lt;code&gt;pyton&lt;/code&gt; is caught.&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;rendering bug&amp;rdquo; of the front matter is gone.&lt;/li&gt;
&lt;li&gt;Also, he problem with the single quote is more obvious to spot. It&amp;rsquo;s less likely to be distracted by all the colors. That one may be subjective: it&amp;rsquo;s what my guts tell me, though.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One more thing: I&amp;rsquo;m also viewing the rendered HTML in a browser next to my Neovim window. Hugo rebuilds the page I&amp;rsquo;m editing after each save, and the browser automatically reloads.&lt;/p&gt;
&lt;p&gt;This has several consequences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, some parts of the highlight are redundant. I&amp;rsquo;m able to see the italics in the browser, I don&amp;rsquo;t need to &lt;em&gt;also&lt;/em&gt; view them as such in the editor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Second, the problem with the &lt;code&gt;{{ref&lt;/code&gt; usage gets caught by the &lt;code&gt;hugo&lt;/code&gt; process itself:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ERROR 2018/10/04 16:36:23 error processing shortcode
  &amp;#34;_internal/shortcodes/ref.html&amp;#34;
  for page &amp;#34;post/0087-demo-syntax-highlight.md&amp;#34;:
    template: _internal/shortcodes/ref.html:1:89:
    executing &amp;#34;_internal/shortcodes/ref.html&amp;#34; at &amp;lt;0&amp;gt;:
    invalid value; expected string
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So let&amp;rsquo;s think about what we learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The syntax highlighting is buggy, and it will never be as good as the HTML rendering. (Especially with Markdown, where each rendering tool has its own quirks).&lt;/li&gt;
&lt;li&gt;It &amp;ldquo;hides&amp;rdquo; important information, like spelling errors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, why do we keep using it?&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For now, I&amp;rsquo;m just turning syntax off for Markdown files. Here&amp;rsquo;s the relevant section in my &lt;code&gt;init.vim&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;augroup textfiles
  autocmd!
  autocmd filetype markdown :setlocal spell spelllang=en | syntax clear
augroup end
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;rsquo;m still using syntax highlight in the other cases.&lt;/p&gt;
&lt;p&gt;But, in the same way the syntax highlighting may be useless (and even harmful) for editing Markdown when a HTML renderer can be used, maybe syntax highlighting is &lt;em&gt;also&lt;/em&gt; useless if &lt;a href=&#34;https://dmerej.info/blog/post/lets-have-a-pint-of-vim-ale/&#34;&gt;a linter can be used directly&lt;/a&gt; to check the code &lt;strong&gt;while it&amp;rsquo;s being typed&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Food for thought …&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 8: Using C&#43;&#43; in an iOS application</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-8-ios/</link>
      <pubDate>Tue, 18 Sep 2018 16:53:30 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-8-ios/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 8 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you came this far after reading part 1 to 7, congrats!&lt;/p&gt;
&lt;p&gt;In this article, we&amp;rsquo;ll use everything we learnt so far and write an iOS application able to show Chuck Norris facts. We&amp;rsquo;ll also learn a few things specific to iOS and Xcode. Let&amp;rsquo;s dive in!&lt;/p&gt;
&lt;h1 id=&#34;introduction-cocoapods&#34;&gt;Introduction: CocoaPods&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction-cocoapods&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;There are many ways to achieve our goal. Several tools exist, but for this post we&amp;rsquo;ll concentrate on &lt;a href=&#34;https://cocoapods.org&#34;&gt;CocoaPods&lt;/a&gt;. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;CocoaPods can be used in two modes:&lt;/p&gt;
&lt;p&gt;First, you can run &lt;code&gt;pod lib create foo&lt;/code&gt;. This will create a &lt;code&gt;Foo.podspec&lt;/code&gt; file. The &lt;em&gt;podspec&lt;/em&gt; describes how to build the &lt;code&gt;foo&lt;/code&gt; library, a bit like a Conan recipe. You can then upload the podspec file and the associated sources to a &lt;em&gt;repository&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Second, you can run &lt;code&gt;pod init&lt;/code&gt; next to an existing Xcode project. This will create an Xcode &lt;em&gt;workspace&lt;/em&gt; and a &lt;code&gt;Podfile&lt;/code&gt; file. You can specify one or several dependencies in the Podfile. Then, when you run &lt;code&gt;pod install&lt;/code&gt;, the podspecs will be fetched and the workspace will be configured so that you can build and use those dependencies in the original Xcode project.&lt;/p&gt;
&lt;p&gt;That way you minimize the interactions with Xcode through its GUI and use code instead.&lt;/p&gt;
&lt;p&gt;So, here&amp;rsquo;s the plan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a &lt;em&gt;CocoaPods library&lt;/em&gt; called &lt;code&gt;ChuckNorrisBindings&lt;/code&gt; in &lt;code&gt;ios/bindings/ChuckNorrisBindings&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a blank iOS application with in the &lt;code&gt;ios/app/ChuckNorris&lt;/code&gt; directory, called ChuckNorris.&lt;/li&gt;
&lt;li&gt;Use CocoaPods to create a dependency between ChuckNorrisBindings and ChuckNorris.&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;li&gt;Profit!&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;the-bindings&#34;&gt;The Bindings&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-bindings&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;cocoapods&lt;/code&gt; is written in Ruby and can be installed with gem:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;gem install cocoapods
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We run &lt;code&gt;pod lib create ChuckNorrisBindings&lt;/code&gt; and answer a few questions:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pod lib create ChuckNorrisBindings
Cloning `https://github.com/CocoaPods/pod-template.git` into `ChuckNorrisBindings`.
...
What platform do you want to use? [ iOS / macOS ]
&amp;gt; ios
What language do you want to use? [ Swift / ObjC ]
&amp;gt; ObjC
Would you like to include a demo application with your library? [ Yes / No ]
&amp;gt; No
Which testing frameworks will you use? [ Specta / Kiwi / None ]
&amp;gt; Specta
Would you like to do view based testing? [ Yes / No ]
&amp;gt; No
What is your class prefix?
CK
...
Running pod install on your new library.
...
Analyzing dependencies
Fetching podspec for `ChuckNorrisBindings` from `../`
Setting up CocoaPods master repo
...
 Ace! you&amp;#39;re ready to go!
 We will start you off by opening your project in Xcode
  open &amp;#39;ChuckNorrisBindings/Example/ChuckNorrisBindings.xcworkspace&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You will note CocoaPods has created lots of files. Among them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ChuckNorrisBindings/Sources&lt;/code&gt;: the sources of the library.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ChuckNorrisBindings.podspec&lt;/code&gt;: the podspec used to build and depend on the ChuckNorrisBindings library&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Example/ChuckNorrisBindings.xcodeproj&lt;/code&gt; the Xcode project to build the sources&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Example/ChuckNorrisBindings.xcworkspace&lt;/code&gt; the Xcode workspace which we can use to:
&lt;ul&gt;
&lt;li&gt;build the library&lt;/li&gt;
&lt;li&gt;build the test framework&lt;/li&gt;
&lt;li&gt;build and run the tests themselves.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If we try to run the tests directly from Xcode, it won&amp;rsquo;t work right away, instead we get this error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Scheme &amp;#34;Pods-ChuckNorrisBindings_Tests&amp;#34; is not configured for testing.
Edit the scheme to enable testing, or cancel the action.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have to fiddle with the schemes CocoaPods generated for us:&lt;/p&gt;
&lt;p&gt;Open the scheme editor:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/manage-schemes.png&#34; alt=&#34;edit the testing scheme&#34;&gt;&lt;/p&gt;
&lt;p&gt;Show the test scheme:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/show-test-scheme.png&#34; alt=&#34;show test scheme&#34;&gt;&lt;/p&gt;
&lt;p&gt;Click the &lt;code&gt;+&lt;/code&gt; bottom at the bottom and select the test target.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/choose-test-target.png&#34; alt=&#34;choose the test target&#34;&gt;&lt;/p&gt;
&lt;p&gt;This time we get an other error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Could not find test host for ChuckNorrisBindings_Tests ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Edit the project settings, under &amp;ldquo;General&amp;rdquo; and switch the Host application form &amp;ldquo;Custom&amp;rdquo; to &amp;ldquo;None&amp;rdquo;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/select-test-host-app.png&#34; alt=&#34;select test host&#34;&gt;&lt;/p&gt;
&lt;p&gt;And it works: a simulator is started and the tests run &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h3 id=&#34;cross-compiling-chucknorris-for-ios&#34;&gt;Cross-compiling ChuckNorris for iOS&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#cross-compiling-chucknorris-for-ios&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Our plan to bind the C++ library for iOS is a combination of techniques we already seen in parts 5 and 6.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll cross-compile ChuckNorris as a static library from macOS to iOS. And then we&amp;rsquo;ll compile the Objective-C code by giving it the paths to the &lt;code&gt;libchucknorris.a&lt;/code&gt; file, the conan dependencies, and the &lt;code&gt;chucknorris.h&lt;/code&gt; C header.&lt;/p&gt;
&lt;p&gt;Before anything, &lt;strong&gt;let&amp;rsquo;s make sure Xcode command line tools are installed&lt;/strong&gt; by running &lt;code&gt;xcode-select --install&lt;/code&gt;. If you are following this tutorial at home, make sure to run this or nothing will work.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create a conan profile called &lt;code&gt;ios&lt;/code&gt; and add a build dependency:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# In ~/.conan/profiles/ios&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[settings]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;os&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;iOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;os.version&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;9.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;arch&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;x86_64&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;compiler&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;apple-clang&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;compiler.version&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;9.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;compiler.libcxx&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;libc++&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;build_type&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;Release&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;os_build&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;Macos&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[build_requires]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;darwin-toolchain/1.0@theodelrieu/stable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For now, we&amp;rsquo;ve hard-coded the x86_64 architecture, because we&amp;rsquo;ll run everything in simulators, and Xcode simulators require this architecture. In order to run the code on actual devices, we&amp;rsquo;ll invoke conan with the correct &lt;code&gt;--settings arch=&amp;lt;arch&amp;gt;&lt;/code&gt; flag. This is similar to what we did in Part 6.&lt;/p&gt;
&lt;p&gt;Note that this time we don&amp;rsquo;t need to write the toolchain recipe ourselves, there is already one on conan-center.&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Then, as we did for Android, we run &lt;code&gt;conan create&lt;/code&gt; for &lt;code&gt;sqlite3&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;cd&lt;/span&gt; conan/sqlite3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conan create . dmerej/test --profile ios --settings &lt;span style=&#34;color:#40ffff&#34;&gt;arch&lt;/span&gt;=x86_64
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we did for Android with the &lt;code&gt;libc++shared.so&lt;/code&gt; file, we patch the ChuckNorris recipe to deal with the copies of all the &lt;code&gt;.a&lt;/code&gt; files, both in the &lt;code&gt;imports()&lt;/code&gt; and &lt;code&gt;package()&lt;/code&gt; methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;imports&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.settings.os == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Android&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;          self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;*libc++_shared.so&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.settings.os == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;iOS&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;          self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;*.a&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, src=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bin/cpp_demo&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/*.so&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;      self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/*.a&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then we can create the ChuckNorris package:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd cpp/ChuckNorris
conan create . dmerej/test --profile ios --settings arch=x86_64
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So far so good.&lt;/p&gt;
&lt;h2 id=&#34;the-podspec&#34;&gt;The podspec&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-podspec&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Note that all the &lt;code&gt;.a&lt;/code&gt; files are somewhere inside &lt;code&gt;~/.conan/data/&lt;/code&gt;. Let&amp;rsquo;s copy them into a &lt;code&gt;nativelibs/x86_64&lt;/code&gt; directory next to the bindings code:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mkdir -p nativelibs/x86_64/
cp \
  ~/.conan/dataChuckNorris/0.2/dmerej/test/package/&amp;lt;id&amp;gt;/*.a
  nativelibs/x86_64/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So that we don&amp;rsquo;t forget, let&amp;rsquo;s add &lt;code&gt;nativelibs&lt;/code&gt; to the &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next we can edit the podspec to specify:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The include directory: it&amp;rsquo;s inside a directory called &lt;code&gt;pod_target_xcconfig&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;vendored&lt;/em&gt; libraries: that&amp;rsquo;s our &lt;code&gt;libchucknorris.a&lt;/code&gt; and &lt;code&gt;libsqlite3.a&lt;/code&gt;. They are called &amp;ldquo;vendored&amp;rdquo; because they won&amp;rsquo;t be compiled by CocoaPods itself, and are not already present on the target operating system either.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;Pod&lt;/span&gt;::&lt;span style=&#34;color:#40ffff&#34;&gt;Spec&lt;/span&gt;.new &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;do&lt;/span&gt; |s|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  s.pod_target_xcconfig = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;HEADER_SEARCH_PATHS&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;${POD_ROOTS}/../../cpp/ChuckNorris/include/&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  s.vendored_libraries = &lt;span style=&#34;color:#40ffff&#34;&gt;Dir&lt;/span&gt;[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;out/*.a&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two remarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Since CocoaPods recipes are written in Ruby, we can use the overloaded &lt;code&gt;[]&lt;/code&gt; operator for &lt;code&gt;Dir&lt;/code&gt; objects to get the full list of files matching the &lt;code&gt;out/*.a&lt;/code&gt; &lt;em&gt;glob&lt;/em&gt; pattern.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;HEADER_SEARCH_PATHS&lt;/code&gt; string contains a &lt;code&gt;${POD_ROOTS}&lt;/code&gt; extension, that will be set by CocoaPods.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note how it does not matter if we are building the &lt;code&gt;ChuckNorrisBindings&lt;/code&gt; CocoaPods library or the &lt;code&gt;ChuckNorris&lt;/code&gt; application: the resulting &lt;code&gt;HEADER_SEARCH_PATHS&lt;/code&gt; will be the same.&lt;/p&gt;
&lt;p&gt;Anyway, we can now run &lt;code&gt;pod update&lt;/code&gt; from the &lt;code&gt;Example&lt;/code&gt; directory to update the Xcode projects and workspace configurations.&lt;/p&gt;
&lt;h1 id=&#34;objective-c&#34;&gt;Objective-C&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#objective-c&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We can use C code directly in Objective-C.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s still dangerous to expose C code directly, so here&amp;rsquo;s how we can proceed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write a CKChuckNorris class. (It&amp;rsquo;s a convention to prefix all the classes in a pod library with the initials of the projects)&lt;/li&gt;
&lt;li&gt;Write a CKChuckNorris+Private category to hide the C code from the consumers of the CKChuckNorris class.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Objective-C&#34; data-lang=&#34;Objective-C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In CKChuckNorris.h */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CKChuckNorris&lt;/span&gt;: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;NSObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@property&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt;* ckPtr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;instancetype&lt;/span&gt;)&lt;span style=&#34;color:#447fcf&#34;&gt;init&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(NSString*) &lt;span style=&#34;color:#447fcf&#34;&gt;getFact&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Objective-C&#34; data-lang=&#34;Objective-C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In CKChuckNorris.m */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#import &amp;#34;CKChuckNorris.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#import &amp;#34;CKChuckNorris+Private.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@implementation&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CKChuckNorris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;instancetype&lt;/span&gt;)&lt;span style=&#34;color:#447fcf&#34;&gt;init&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt; = [&lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt; init];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt; createCkPtr];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(NSString *)&lt;span style=&#34;color:#447fcf&#34;&gt;getFact&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt; getFactImpl];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Objective-C&#34; data-lang=&#34;Objective-C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In CKChuckNorris+Private.h */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#import &amp;#34;CKChuckNorris.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CKChuckNorris&lt;/span&gt; (Private)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;instancetype&lt;/span&gt;) &lt;span style=&#34;color:#447fcf&#34;&gt;createCkPtr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(NSString*) &lt;span style=&#34;color:#447fcf&#34;&gt;getFactImpl&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So far we have just &lt;em&gt;declared&lt;/em&gt; the  &lt;code&gt;createCKPtr&lt;/code&gt; and &lt;code&gt;getFactImpl&lt;/code&gt; methods.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s time to &lt;em&gt;define&lt;/em&gt; them in the &lt;code&gt;CKChuckNorris+Private.m&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Objective-C&#34; data-lang=&#34;Objective-C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In CKChuckNorris+Private.m */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#import &amp;#34;CKChuckNorris+Private.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;#34;chucknorris.h&amp;#34;   // &amp;lt;- Our C header file&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@implementation&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CKChuckNorris&lt;/span&gt; (Private)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;instancetype&lt;/span&gt;)&lt;span style=&#34;color:#447fcf&#34;&gt;createCkPtr&lt;/span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;.ckPtr = chuck_norris_init();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(NSString*)&lt;span style=&#34;color:#447fcf&#34;&gt;getFactImpl&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* fact = chuck_norris_get_fact(&lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;.ckPtr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; [NSString stringWithCString:fact encoding:NSUTF8StringEncoding];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how the &lt;em&gt;only&lt;/em&gt; file that depends on the &lt;code&gt;chucknorris.h&lt;/code&gt; C header file is the &lt;em&gt;private implementation&lt;/em&gt; of the &lt;code&gt;CKChuckNorris&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a similar technique known as &amp;ldquo;PIMPL&amp;rdquo; (pointer to implementation) you can use in C++ code to achieve the same kind of isolation.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s now time to edit the tests:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Objective-C&#34; data-lang=&#34;Objective-C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In Tests.m */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;describe(&lt;span style=&#34;color:#ed9d13&#34;&gt;@&amp;#34;ChuckNorris&amp;#34;&lt;/span&gt;, ^{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  it(&lt;span style=&#34;color:#ed9d13&#34;&gt;@&amp;#34;can get version&amp;#34;&lt;/span&gt;, ^{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    expect([CKChuckNorris versionString]).to.equal(&lt;span style=&#34;color:#ed9d13&#34;&gt;@&amp;#34;0.1&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  it(&lt;span style=&#34;color:#ed9d13&#34;&gt;@&amp;#34;can get a fact&amp;#34;&lt;/span&gt;, ^{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CKChuckNorris* ck = [[CKChuckNorris alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSString* fact = [ck getFact];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    expect(fact).toNot.beEmpty();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NSLog(&lt;span style=&#34;color:#ed9d13&#34;&gt;@&amp;#34;Got fact: %@&amp;#34;&lt;/span&gt;, fact);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And see if they pass:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Undefined symbols for architecture x86_64:
  &amp;#34;operator delete(void*)&amp;#34;, referenced from:
      _chuck_norris_version in libchucknorris.a(c_wrapper.cpp.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Whoops, we forgot to add the dependency to the C++ library. It&amp;rsquo;s less hard than in the Android case, since they always have the same name for iOS:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;Pod&lt;/span&gt;::&lt;span style=&#34;color:#40ffff&#34;&gt;Spec&lt;/span&gt;.new &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;do&lt;/span&gt; |s|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  s.vendored_libraries = ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  s.libraries = [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;c++&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;c++abi&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;libc++&lt;/code&gt; and &lt;code&gt;libc++abi&lt;/code&gt; are found on the target operating system, hence we use the &lt;code&gt;libraries&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;We can now try again, and this time the tests pass \o/.&lt;/p&gt;
&lt;h1 id=&#34;the-gui&#34;&gt;The GUI&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-gui&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We create the Objective-C application from Xcode.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/create-project.png&#34; alt=&#34;Creating Xcode project&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then we edit the main storyboard to add a stack view, a text field and a button:&lt;/p&gt;
&lt;p&gt;We drag and drop the components from the designer view to the code, while keeping the &lt;code&gt;ctrl&lt;/code&gt; key pressed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/assistant-editor.png&#34; alt=&#34;Using the assistant&#34;&gt;&lt;/p&gt;
&lt;p&gt;For now, we&amp;rsquo;ll just set the text view to the string &lt;code&gt;Hello&lt;/code&gt; when the button is clicked:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In ViewController.m */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;IBAction&lt;/span&gt;)&lt;span style=&#34;color:#447fcf&#34;&gt;onClick:&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;id&lt;/span&gt;)&lt;span style=&#34;color:#40ffff&#34;&gt;sender&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;.textView.text = &lt;span style=&#34;color:#ed9d13&#34;&gt;@&amp;#34;Hello&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK, that works.&lt;/p&gt;
&lt;p&gt;Now we can run &lt;code&gt;pod init&lt;/code&gt; and edit the Podfile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ruby&#34; data-lang=&#34;ruby&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;target &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;ChuckNorris&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  pod &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;ChuckNorrisBindings&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;:path&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;../bindings/&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We took a small shortcut here. Rather than deploying the ChuckNorrisBindings to a spec repository, we just tell the Podfile to get the podspec directly from the file system.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s check this works:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd ios/app
$ pod update
...
Downloading dependencies
...
Sending stats
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Looks OK.&lt;/p&gt;
&lt;p&gt;All that&amp;rsquo;s left to do is add a &lt;code&gt;CKChuckNorris*&lt;/code&gt; pointer to the controller, set it in &lt;code&gt;viewDidLoad&lt;/code&gt; and call the &lt;code&gt;getFact()&lt;/code&gt; method when the button is clicked:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In ViewController.h */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#import &amp;lt;UIKit/UIKit.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#import &amp;#34;CKChuckNorris.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@interface&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ViewController&lt;/span&gt; : &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;UIViewController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@property&lt;/span&gt; CKChuckNorris* ck;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;@end&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-objective-c&#34; data-lang=&#34;objective-c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- (&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt;)&lt;span style=&#34;color:#447fcf&#34;&gt;viewDidLoad&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt; viewDidLoad];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;.ck = [[CKChuckNorris alloc] init];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;IBAction&lt;/span&gt;)&lt;span style=&#34;color:#447fcf&#34;&gt;onClick:&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;id&lt;/span&gt;)&lt;span style=&#34;color:#40ffff&#34;&gt;sender&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;.textView.text = [&lt;span style=&#34;color:#24909d&#34;&gt;self&lt;/span&gt;.ck getFact];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can now run the application inside a simulator:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/simulator.png&#34; alt=&#34;ChuckNorris application on a simulator&#34;&gt;&lt;/p&gt;
&lt;p&gt;Yippee!&lt;/p&gt;
&lt;h1 id=&#34;dealing-with-the-other-architectures&#34;&gt;Dealing with the other architectures&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#dealing-with-the-other-architectures&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s try to build an &lt;code&gt;.ipa&lt;/code&gt;, i.e an application file that can be installed on real devices.&lt;/p&gt;
&lt;p&gt;The first step is to generate an &lt;em&gt;archive&lt;/em&gt; of our application. To do this, we can use the &amp;ldquo;Archive&amp;rdquo; entry in the &amp;ldquo;Product&amp;rdquo; menu.&lt;/p&gt;
&lt;p&gt;Right now it&amp;rsquo;s disabled, but we can fix this by selecting the &amp;ldquo;Generic iOS Device&amp;rdquo; next to the play/stop buttons in the bottom left.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s click on it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ld: warning: ignoring file /nativelibs/x86_64/libchucknorris.a, file was built
  for archive which is not the architecture being linked (arm64)
error: Undefined symbols for architecture arm64:
  &amp;#34;_chuck_norris_version&amp;#34;, referenced from:
  +[CKChuckNorris(Private) versionStringImpl] in
    libChuckNorrisBindings.a(CKChuckNorris.o)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You read this right: the fact the &lt;code&gt;.a&lt;/code&gt; was &lt;strong&gt;not build for the correct CPU architecture&lt;/strong&gt; is a &lt;em&gt;warning&lt;/em&gt;, and after that we get a generic error about the symbol being not found. The morale of the story is: when you have a compilation failure, start at the top of the compiler output :)&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s try and add support for Arm 64bits. We can start by cross-compiling sqlite3 like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;cd&lt;/span&gt; sqlite3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conan create . dmerej/test --profile ios --settings &lt;span style=&#34;color:#40ffff&#34;&gt;arch&lt;/span&gt;=armv8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that Conan and Xcode use different names for this architecture (&lt;code&gt;armv8&lt;/code&gt; and &lt;code&gt;arm64&lt;/code&gt; respectively).&lt;/p&gt;
&lt;p&gt;Now, for the x86_64 architecture we manually copied files from &lt;code&gt;.conan/data&lt;/code&gt; to &lt;code&gt;nativelibs/x86_64&lt;/code&gt;. This is not ideal. Instead, we can use &lt;code&gt;conan install&lt;/code&gt; (to install the deps), then &lt;code&gt;conan build&lt;/code&gt; (to build the ChuckNorris library), and finally &lt;code&gt;conan package&lt;/code&gt; to copy the libraries and headers (to run the code that was in the &lt;code&gt;package()&lt;/code&gt; function of the recipe, remember?):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;color:#24909d&#34;&gt;cd&lt;/span&gt; cpp/ChuckNorris
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ conan install . --profile ios --settings &lt;span style=&#34;color:#40ffff&#34;&gt;arch&lt;/span&gt;=armv8 &lt;span style=&#34;color:#ed9d13&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&lt;/span&gt;    --install-folder build/ios/armv8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ conan build . --build-folder build/ios/armv8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ connan package . --build-folder build/ios/armv8 &lt;span style=&#34;color:#ed9d13&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&lt;/span&gt;    --package-folder nativelibs/armv8
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how the &amp;ldquo;install folder&amp;rdquo; for &lt;code&gt;conan install&lt;/code&gt; matches the &amp;ldquo;build folder&amp;rdquo; for &lt;code&gt;conan build&lt;/code&gt; and &lt;code&gt;conan package&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also note how the profile and settings are only used by &lt;code&gt;conan install&lt;/code&gt;. After this, everything conan needs to know can be found in the build directory.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s do the same for &amp;lsquo;armv7&amp;rsquo;, &amp;lsquo;armv7s&amp;rsquo;, and &amp;lsquo;x86&amp;rsquo;. Armv7 and armv7s are architectures used by older iOS devices, and x86 is used by 32 bits simulators.&lt;/p&gt;
&lt;p&gt;Since this is a bit tedious by hand, we&amp;rsquo;ll use the &lt;a href=&#34;https://github.com/dmerejkowsky/chucknorris/blob/master/cpp/ChuckNorris/ios_build.py&#34;&gt;build_ios.py&lt;/a&gt; script. &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Now, instead of trying to build the ChuckNorrisBindings several times, once per architecture, (which is hard to do when using CocoaPods), we can use &lt;em&gt;fat libraries&lt;/em&gt; instead. Fat libraries are just like regular libraries, except they can contain code for multiple architectures.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s create a &lt;code&gt;nativelibs/universal&lt;/code&gt; folder containing fat &lt;code&gt;liqsqlite3.a&lt;/code&gt; and fat &lt;code&gt;libchucknorris.a&lt;/code&gt; libraries:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd nativelibs/universal
lipo -create -output libsqlite3.a ../*/lib/libsqlite3.a
lipo -create -output libchucknorris.a ../*/lib/libchucknorris.a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can check with &lt;code&gt;lipo -info&lt;/code&gt; that this worked:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ lipo -info libchucknorris.a
Architectures in the fat file: libchucknorris.a are:
  armv7 armv7s i386 x86_64 arm64
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then we fix the podspec:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- s.vendored_libraries = Dir[&amp;#34;nativelibs/x86_64/*.a&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ s.vendored_libraries = Dir[&amp;#34;nativelibs/universal/*.a&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We re-generate the Xcode project with &lt;code&gt;pod update --ro-repo-update&lt;/code&gt;. This time the &amp;ldquo;Archive&amp;rdquo; step triggers no errors, and we are faced with this window:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/archive.png&#34; alt=&#34;xcode archive output&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;signing-the-archive&#34;&gt;Signing the archive&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#signing-the-archive&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We now need to build a re-distributable application from the archive. The depends on your Xcode profiles and certificates. Here&amp;rsquo;s what worked for me, your mileage may vary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Select &amp;ldquo;export&amp;rdquo; on the right pane&lt;/li&gt;
&lt;li&gt;Choose &amp;ldquo;Ad Hoc&amp;rdquo; method of distribution&lt;/li&gt;
&lt;li&gt;Then tick the &amp;ldquo;Rebuild from Bitcode&amp;rdquo; option.&lt;/li&gt;
&lt;li&gt;Let Xcode do the signing and save the &lt;code&gt;.ipa&lt;/code&gt; in a folder named based on the current date.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, go to Xcode &amp;ldquo;Window&amp;rdquo; menu, select &amp;ldquo;Devices&amp;rdquo;, and drag and drop the &amp;ldquo;.ipa&amp;rdquo; from the date folder to the list of applications installed on this device.&lt;/p&gt;
&lt;p&gt;And here&amp;rsquo;s the result (taken from my crappy Android phone):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xcode/victory.jpg&#34; alt=&#34;ChuckNorris running on a real device&#34;&gt;&lt;/p&gt;
&lt;p&gt;Victory!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;That&amp;rsquo;s the end of the Chuck Norris series. I hope you had fun, I hope you learned something new. See you next time!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I heard Carthage is also a good option. Did not try it, though.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;That is, if you already generated a signing certificate. If not, follow the instructions printed in the logs.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;This recipe was written and shared by my nice colleague Théo Delrieu from &lt;a href=&#34;https://tanker.io&#34;&gt;tanker.io&lt;/a&gt;. Say thanks!&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Which is not far from &lt;a href=&#34;https://dmerej.info/blog/post/introducing-tips-from-a-build-farmer/&#34;&gt;the CI script&lt;/a&gt; we use at work by the way.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Comparing directories: a case study</title>
      <link>https://dmerej.info/blog/post/comparing-directories/</link>
      <pubDate>Sat, 08 Sep 2018 12:36:50 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/comparing-directories/</guid>
      <description>&lt;h1 id=&#34;the-problem&#34;&gt;The problem&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-problem&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s say we have a directory called O that contains a large number of subdirectories and files.&lt;/p&gt;
&lt;p&gt;We find ourselves with two different directories, A and B. Each of them started as a copy of O, but then, in each of them, some files were changed, some were added or removed, and we don&amp;rsquo;t know which ones.&lt;/p&gt;
&lt;p&gt;We want to compare the contents of A and B, for instance to merge them back into O.&lt;/p&gt;
&lt;p&gt;There are several ways to solve the problem, depending on the situation.  Let&amp;rsquo;s take a look.&lt;/p&gt;
&lt;h1 id=&#34;using-a-gui&#34;&gt;Using a GUI&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-a-gui&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;For our first case, let&amp;rsquo;s assume A and B are on our development computer and we have a graphical session opened.&lt;/p&gt;
&lt;p&gt;We can use many GUI tools for this task, here&amp;rsquo;s an example with &lt;a href=&#34;http://kdiff3.sourceforge.net/&#34;&gt;Kdiff3&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/kdiff3.png&#34; alt=&#34;kdiff3 screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;On the top left pane we have an overview of all the differences between the A and B directories, and we can see that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;bar/eggs&lt;/code&gt; and &lt;code&gt;bar/spam&lt;/code&gt; directories are identical between A and B&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s a new file named &lt;code&gt;bar/new.txt&lt;/code&gt; in A&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s a new file named &lt;code&gt;baz/six.txt&lt;/code&gt; in B&lt;/li&gt;
&lt;li&gt;The file &lt;code&gt;foo/a.txt&lt;/code&gt; was changed both in A and B&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the bottom panes, since &lt;code&gt;a.txt&lt;/code&gt; is selected, we can see the differences in the contents.&lt;/p&gt;
&lt;h1 id=&#34;using-the-command-line&#34;&gt;Using the command line&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-the-command-line&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now let&amp;rsquo;s assume A and B are both on a remote server running Linux&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; and we can&amp;rsquo;t open a remote graphical session there.&lt;/p&gt;
&lt;p&gt;What are our options?&lt;/p&gt;
&lt;p&gt;Well, we could use a &lt;em&gt;coreutils&lt;/em&gt; command.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Coreutils&lt;/em&gt; is a package which is both very old and present in almost any Linux operating system. It contains a collection of useful, small command line programs. Even when it is not installed, an other package (like &lt;code&gt;busybox&lt;/code&gt;) is usually here to provide similar functionality.&lt;/p&gt;
&lt;p&gt;Anyway, there is a coreutils command named &lt;code&gt;diff&lt;/code&gt; we can use for the task at hand:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ diff --recursive a b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Only in a/bar: new.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Only in b/baz: six.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;diff --recursive a/foo/a.txt b/foo/a.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1c1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt; this is a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; this is modified a
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Boom! All the info we need.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;diff&lt;/code&gt; offers lots of ways to tweak its behavior&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. For instance, we can get more succinct info with the &lt;code&gt;--brief&lt;/code&gt; option:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ diff --recursive --brief a b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Only in a/bar: new.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Only in b/baz: six.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Files a/foo/a.txt and b/foo/a.txt differ
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By the way, if git is installed on the remote server, we can also use it, with nice options like &lt;code&gt;--stat&lt;/code&gt; or &lt;code&gt;--word-diff&lt;/code&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git diff --stat a b
 a/bar/new.txt =&amp;gt; /dev/null | 1 -
 /dev/null =&amp;gt; b/baz/six.txt | 1 +
 {a =&amp;gt; b}/foo/a.txt         | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;remote-directories&#34;&gt;Remote directories&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#remote-directories&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now let&amp;rsquo;s assume A and B are on two &lt;em&gt;different&lt;/em&gt; remote servers: let&amp;rsquo;s call them &lt;em&gt;abbot&lt;/em&gt; and &lt;em&gt;costello&lt;/em&gt; respectively.&lt;/p&gt;
&lt;p&gt;Also, let&amp;rsquo;s assume A and B contains lots of big files, so we cannot copy the A directory from abbot to costello and use the previous technique. We can, however, transfer small files between the two servers. Here&amp;rsquo;s we can do.&lt;/p&gt;
&lt;p&gt;First, we log in to abbot:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ssh user@abbot
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, we go inside the &lt;code&gt;a&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then we run the following command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;find . | sort &amp;gt; ~/manifest-a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;Explanation&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;find .&lt;/code&gt; lists all the files and directories inside the current working directory.&lt;/li&gt;
&lt;li&gt;The order of the files returned by find are not deterministic and can change form one file system to another, so we use a pipe (&lt;code&gt;|&lt;/code&gt;) to take the output of &lt;code&gt;find&lt;/code&gt; and pass it to the &lt;code&gt;sort&lt;/code&gt; command. (&lt;code&gt;sort&lt;/code&gt; is also part of the coreutils package).&lt;/li&gt;
&lt;li&gt;Finally, we use an angle bracket (&lt;code&gt;&amp;gt;&lt;/code&gt;) to write the output of &lt;code&gt;sort&lt;/code&gt; to a file in the home directory: (&lt;code&gt;~/manifest-a&lt;/code&gt;): we must not write the manifest-a file inside the &lt;code&gt;a&lt;/code&gt; directory, otherwise the manifest may contain itself!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, we do the same on costello:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ssh user@costello
cd b
find . -type f | sort &amp;gt; ~/manifest-b
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then we use &lt;code&gt;scp&lt;/code&gt; to transfer the A manifest to costello:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# On abbot
scp manifest-a user@costello:
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we have two text files on costello, both containing a list of all the files. So, we use &lt;code&gt;diff&lt;/code&gt; on the manifest files themselves:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diff ~/manifest-*
...
-./bar/new.txt
...
...
+./bar/six.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That takes care of the contents of the directories. What about contents of the files themselves ?&lt;/p&gt;
&lt;p&gt;Well, we can use another coreutils tools called &lt;code&gt;shasum&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;shasum&lt;/code&gt; can be used to compute a &lt;em&gt;checksum&lt;/em&gt; of the contents of a given file. It will generate the same output if the contents are the same, and if two files are different, there&amp;rsquo;s almost zero chance their checksum will be equal. &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;We can call &lt;code&gt;shasum&lt;/code&gt; with a list of files as arguments, like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;shasum file1.txt file2.txt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here we need to call shasum with the whole list of files, so we call &lt;code&gt;find .&lt;/code&gt; again but with the &lt;code&gt;-type f&lt;/code&gt; option to select only the files and ignore the directories. This gives us a list of &lt;em&gt;lines&lt;/em&gt;, so we use &lt;code&gt;xargs&lt;/code&gt; (also in coreutils) to convert them into a list of command line arguments&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;, and finally write the result in a &lt;code&gt;a.shasum&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;find . -type f | xargs shasum &amp;gt; ~/a.shasum
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here are the contents of the &lt;code&gt;a.shasum&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;791c4ba196e0faea35e0c5fbe46e64da  bar/eggs/two.txt
23f4a2592b2e4dee0444983a6e53c23e  bar/new.txt
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can transfer the &lt;code&gt;a.shasum&lt;/code&gt; file to costello:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ scp a.shasum user@costello:
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, we can use &lt;code&gt;shasum&lt;/code&gt; again with the &lt;code&gt;--check&lt;/code&gt; option: it will read each line, parsing the file name and expected checksum, then compute the &lt;em&gt;actual&lt;/em&gt; checksum for the given file and check if it matches the expected value:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd b
$ shasum --check ~/a.shasum
./bar/eggs/two.txt: OK
./bar/spam/one.txt: OK
...
./foo/a.txt: FAILED
...
shasum: WARNING: 1 of 5 computed checksums did NOT match
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And we&amp;rsquo;re done: from the differences of the manifests we know which file are missing or were added, and from the list of checksums we know which files differ.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We saw that we can use nothing but command line tools from the &lt;code&gt;coreutils&lt;/code&gt; package to compare the contents of two directories: the technique we used was working exactly the same way several decades ago, and will probably continue to work for a long time.&lt;/p&gt;
&lt;p&gt;So, if you liked the techniques show here, here&amp;rsquo;s my advice to you: next time you are confronted with a task similar to the one we just studied, take a look at all of the coreutils documentation and try using them. If you do this often, after a while you&amp;rsquo;ll have gained a nice addition to your skill set.&lt;/p&gt;
&lt;p&gt;Oh, and if you think &amp;ldquo;this is all useless&amp;rdquo;, please read this &lt;a href=&#34;https://adamdrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html&#34;&gt;enlightening paper&lt;/a&gt; called &lt;em&gt;Command-line Tools can be 235x Faster than your Hadoop Cluster&lt;/em&gt; :)&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I hear there are people running operating systems other than Linux on remote servers. I&amp;rsquo;m sorry if this is the case for you.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;If you&amp;rsquo;d like to see all of what &lt;code&gt;diff&lt;/code&gt; can do, feel free to run &lt;code&gt;man diff&lt;/code&gt; and be amazed!&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Git is smart enough to see that neither A and B are inside a directory it controls, and if A and B &lt;em&gt;were&lt;/em&gt; inside a git working tree, you could use the &lt;code&gt;--no-index&lt;/code&gt; option, as explained &lt;a href=&#34;https://git-scm.com/docs/git-diff#git-diff-emgitdiffemltoptionsgt--no-index--ltpathgtltpathgt&#34;&gt;in the documentation&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;You may already have heard of &lt;em&gt;md5 sum&lt;/em&gt;: it works exactly the same way but uses an older algorithm to compute the checksum and its usage is generally discouraged.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;If you use zsh you can also ask it to list all the files directly with a &lt;em&gt;glob&lt;/em&gt; extension, like this: &lt;code&gt;shasum **/*(.) &amp;gt; ~/a.md5&lt;/code&gt;. Yeah zsh!&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Tips From a Build Farmer - Part 2: Some concepts</title>
      <link>https://dmerej.info/blog/post/tips-from-a-build-farmer-part-2-some-concepts/</link>
      <pubDate>Tue, 28 Aug 2018 18:17:04 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/tips-from-a-build-farmer-part-2-some-concepts/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 2 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-tips-from-a-build-farmer/&#34;&gt;Tips From a Build Farmer&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In this article we&amp;rsquo;ll define a few concepts that we&amp;rsquo;re going to use in the rest of this series.&lt;/p&gt;
&lt;p&gt;But first, let&amp;rsquo;s look at some Java code! &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h1 id=&#34;fruits-and-apples&#34;&gt;Fruits and apples&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#fruits-and-apples&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Fruit&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Apple&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extends&lt;/span&gt; Fruit {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;final&lt;/span&gt; String type;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;Apple&lt;/span&gt;(String type) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;type&lt;/span&gt; = type;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;func&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		List&amp;lt;Fruit&amp;gt; fruitList = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; ArrayList&amp;lt;Fruit&amp;gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		Apple golden = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; Apple(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;golden&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		fruitList.&lt;span style=&#34;color:#bbb&#34;&gt;add&lt;/span&gt;(golden);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s clear that the &lt;code&gt;Apple&lt;/code&gt; class is not really an apple. It&amp;rsquo;s a bunch of data and methods that identifies an apple via a &lt;code&gt;type&lt;/code&gt; string. We can say that the Apple class is a &lt;em&gt;metaphor&lt;/em&gt; for the real apple object.&lt;/p&gt;
&lt;p&gt;But note that &lt;code&gt;fruitList&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a list of fruits! It&amp;rsquo;s a slice of memory containing objects of a certain type, and if you forget that, you&amp;rsquo;re about to get nasty compilation failures such as this one:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Apple firstFruit = fruitList.get(0);

foo.java:21: error: incompatible types: Fruit cannot be converted to Apple
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can solve that with generics of course, but this is not my point.&lt;/p&gt;
&lt;p&gt;My point is that as programmers we are surrounded with metaphors all day long, and sometimes without realizing it. After all, all we do is write text that ultimately is converted to a sequence of zeros and ones and ran on a piece of silicon.&lt;/p&gt;
&lt;p&gt;We create abstractions and encapsulations to be able to reason about the code we write, and we often do that with metaphors.&lt;/p&gt;
&lt;p&gt;We also really care about naming. For instance, you could argue the &lt;code&gt;type&lt;/code&gt; field of the Apple class should be named &lt;code&gt;variety&lt;/code&gt; instead, because this word already has several meanings for any developer.&lt;/p&gt;
&lt;p&gt;But metaphor are not only used by developers.&lt;/p&gt;
&lt;h1 id=&#34;why-you-should-care&#34;&gt;Why you should care&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#why-you-should-care&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;If you read about Agile or XP, you will find out there&amp;rsquo;s a &lt;em&gt;programming practice&lt;/em&gt; called &lt;em&gt;System Metaphor&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;It goes with a bunch of other disciplines such as Test Driven Development, Sustainable Peace, and Collective Code Ownership. You can find &lt;a href=&#34;https://en.wikipedia.org/wiki/Extreme_programming_practices&#34;&gt;the whole list on Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Among programmers we sometimes don&amp;rsquo;t think too much about metaphors because we can still look at the &lt;em&gt;actual code implementation&lt;/em&gt;  (or comments) to figure out what the name means.&lt;/p&gt;
&lt;p&gt;Things change when we need to communicate with people outside the team, such as Product Owners, Marketing or Sales. We use metaphors when we talk to them about features or components of our systems.&lt;/p&gt;
&lt;p&gt;Thus, coming up with good metaphors is the only way to communicate effectively between business and tech teams. We have to come up with a &lt;em&gt;common vocabulary&lt;/em&gt;  that everyone agrees on.&lt;/p&gt;
&lt;p&gt;This means, among other things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoiding using the same word for different things&lt;/li&gt;
&lt;li&gt;Making sure each word means the &lt;em&gt;same thing&lt;/em&gt; for everyone.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, this is why I wanted to talk about metaphors. The concepts I&amp;rsquo;ll be listing below can also be used as such to communicate between people both inside and outside your team.&lt;/p&gt;
&lt;h1 id=&#34;concepts&#34;&gt;Concepts&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#concepts&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The concepts are listed in a top-bottom manner. So if you encounter a term you don&amp;rsquo;t understand, just keep reading!&lt;/p&gt;
&lt;h2 id=&#34;continuous-integration&#34;&gt;Continuous Integration&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#continuous-integration&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Continuous Integration&lt;/em&gt;, or CI for short, is any situation where there exist &lt;em&gt;scripts&lt;/em&gt; running on a &lt;em&gt;build farm&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;ci-scripts&#34;&gt;CI Scripts&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#ci-scripts&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;scripts&lt;/em&gt; are usually written in an &amp;ldquo;scripting language&amp;rdquo; (hence there name).&lt;/p&gt;
&lt;p&gt;They have access to some or all the source code and can do many things: compiling, running some tests, produce deliveries, deploy new servers, and so on &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;They can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run automatically upon certain events (like a merge request being created)&lt;/li&gt;
&lt;li&gt;Run automatically on specific hours (for instance, everyday at 9 AM)&lt;/li&gt;
&lt;li&gt;Be triggered by a manual action (like running a separate program or using a Web interface).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;build-farm&#34;&gt;Build Farm&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#build-farm&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;build farm&lt;/em&gt; is made of two things. A set of &lt;em&gt;runners&lt;/em&gt;, and a &lt;em&gt;coordinator&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There may be just one runner, and the coordinator may be running on the same machine as the runner, it does not matter; what matters is that runners and coordinators do different things.&lt;/p&gt;
&lt;h2 id=&#34;runner&#34;&gt;Runner&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#runner&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A runner is any machine on which the scripts run. That&amp;rsquo;s all.&lt;/p&gt;
&lt;h2 id=&#34;coordinator&#34;&gt;Coordinator&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#coordinator&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A coordinator:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Listens to the &lt;em&gt;triggers&lt;/em&gt; listed above,&lt;/li&gt;
&lt;li&gt;Dispatches the execution of the scripts on one or several machines among the runners,&lt;/li&gt;
&lt;li&gt;Aggregates the results of those executions. Those can be test reports, logs, files, etc. &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that if you&amp;rsquo;re using Jenkins, the coordinator is called &lt;em&gt;master&lt;/em&gt;, and the runners are called &lt;em&gt;nodes&lt;/em&gt; or &lt;em&gt;slaves&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;job&#34;&gt;Job&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#job&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;job&lt;/em&gt; is a script plus a &lt;em&gt;configuration&lt;/em&gt;. The configuration contains at least the specifications for the triggers, but may also contain mappings of keys and values.&lt;/p&gt;
&lt;h2 id=&#34;build&#34;&gt;Build&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#build&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;build&lt;/em&gt; is the execution of a job.&lt;/p&gt;
&lt;p&gt;Usually, builds have a &lt;em&gt;number&lt;/em&gt;, and jobs have a &lt;em&gt;name&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;P.S: I know that &amp;ldquo;build&amp;rdquo; has many other meanings in the programming world, but I don&amp;rsquo;t have a better one.&lt;/p&gt;
&lt;h2 id=&#34;failure-and-success&#34;&gt;Failure and success&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#failure-and-success&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Builds have &lt;strong&gt;only one way&lt;/strong&gt; to &lt;em&gt;succeed&lt;/em&gt;, and many ways to &lt;em&gt;fail&lt;/em&gt;. (The script could not run, the compilation failed, all the tests but one passed, etc. ).&lt;/p&gt;
&lt;p&gt;By extension, we say that a job is &lt;em&gt;failing&lt;/em&gt; when the most recent build failed. We say that the job is &lt;em&gt;stable&lt;/em&gt; if the last build succeed. Thus a job can &lt;em&gt;go from stable to failing&lt;/em&gt;, or &lt;em&gt;be back to stable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Jobs can have other states depending on the coordinator such as &amp;ldquo;skipped&amp;rdquo;, &amp;ldquo;starting&amp;rdquo;, or &amp;ldquo;cancelled&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Side note: Jenkins assigns colors to builds, such as &amp;ldquo;yellow&amp;rdquo; when the compilation is OK but some tests are failing. For me a yellow build is just an other kind of &lt;em&gt;failed&lt;/em&gt; build. &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;notification&#34;&gt;Notification&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#notification&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a job reaches a certain state, you may use a &lt;em&gt;notification&lt;/em&gt; to communicate the event to some humans.&lt;/p&gt;
&lt;p&gt;For instance, if a build triggered by a pull request fails, an e-mail may be sent by the coordinator to its author.&lt;/p&gt;
&lt;h2 id=&#34;step&#34;&gt;Step&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#step&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We saw that scripts can do many various tasks. Scripts often go through a series of &lt;em&gt;steps&lt;/em&gt;, like our example in &lt;a href=&#34;https://dmerej.info/blog/post/tips-from-a-build-farmer-part-1-ci-scripts-are-scary/&#34;&gt;CI scripts are scary&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fetch the code&lt;/li&gt;
&lt;li&gt;Compile everything&lt;/li&gt;
&lt;li&gt;Run the tests&lt;/li&gt;
&lt;li&gt;Generate an archive&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Usually a failure in one of the steps causes the script to terminate immediately (but not always).&lt;/p&gt;
&lt;p&gt;Also, the series of steps may differ from one job to an other. For instance, you may want the &amp;ldquo;deploy to production&amp;rdquo; step to only run for certain triggers :P&lt;/p&gt;
&lt;h2 id=&#34;artifact&#34;&gt;Artifact&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#artifact&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An &lt;em&gt;artifact&lt;/em&gt; is a file produced by one or several steps. Artifacts may be exchanged across jobs, in some cases &lt;em&gt;via&lt;/em&gt; the coordinator, but other mechanisms may be used.&lt;/p&gt;
&lt;h2 id=&#34;delivery&#34;&gt;Delivery&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#delivery&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;delivery&lt;/em&gt; is an artifact that can be used by your customers. Deliveries are often deployed to a download page.&lt;/p&gt;
&lt;h2 id=&#34;deployment&#34;&gt;Deployment&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#deployment&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;deployment&lt;/em&gt; is a special kind of job that consists in either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Uploading some files to a remote location&lt;/li&gt;
&lt;li&gt;Updating some code that is running somewhere else&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the second case you may:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Upload the source files directly to the server. You may do this for sites written in PHP for instance.&lt;/li&gt;
&lt;li&gt;Run some Ansible Playbooks&lt;/li&gt;
&lt;li&gt;Build and upload a Docker image to a container registry and then ask some nodes in a cluster to use the new docker image&lt;/li&gt;
&lt;li&gt;&amp;hellip; or any other technique&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since deployments are just jobs, they &lt;em&gt;also&lt;/em&gt; have only one way to succeed and many ways to fail …&lt;/p&gt;
&lt;h2 id=&#34;environment&#34;&gt;Environment&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#environment&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An environment is just a group of machines where a certain kind deployment occurs.&lt;/p&gt;
&lt;p&gt;For instance, you may decide that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every deployment triggered by a push on the master branch will go to an environment called &amp;ldquo;pre-production&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Every deployment triggered by a tag starting with &amp;lsquo;v&amp;rsquo; will go to an environment called &amp;ldquo;production&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, GitLab CI has an &lt;a href=&#34;https://docs.gitlab.com/ee/ci/environments.html&#34;&gt;excellent support for environments&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;And that&amp;rsquo;s the vocabulary I will be using. I hope you&amp;rsquo;ll find it useful.&lt;/p&gt;
&lt;p&gt;Next time we&amp;rsquo;ll answer the number 1 question: &amp;ldquo;What programming language should I use to write CI scripts?&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;You can skip directly to the &lt;a href=&#34;#concepts&#34;&gt;concepts section&lt;/a&gt; if you want, but I wanted to talk about development practices a little bit.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Note that I&amp;rsquo;m including Continuous Delivery (CD) inside CI. Your mileage may vary.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Plus I&amp;rsquo;m colorblind&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Tips From a Build Farmer - Part 1: CI scripts are scary</title>
      <link>https://dmerej.info/blog/post/tips-from-a-build-farmer-part-1-ci-scripts-are-scary/</link>
      <pubDate>Mon, 20 Aug 2018 10:35:17 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/tips-from-a-build-farmer-part-1-ci-scripts-are-scary/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 1 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-tips-from-a-build-farmer/&#34;&gt;Tips From a Build Farmer&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an simple yet somewhat realistic CI script, in Bash:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;fetching latest changes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git fetch
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git reset --hard @{u}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiling&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;running tests&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make &lt;span style=&#34;color:#24909d&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;generating archive&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;DESTDIR&lt;/span&gt;=/tmp/foo make install
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;cd&lt;/span&gt; /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;tar cvfz foo.tar.gz foo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code fetches the latest changes, compile the code, runs the tests and finally generates an archive.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s so scary about those few lines? Isn&amp;rsquo;t this just &lt;em&gt;boring&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Well, let&amp;rsquo;s have a look, and note that everything I&amp;rsquo;m about to tell you is  &lt;strong&gt;based on true stories.&lt;/strong&gt; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;One last thing before we start: let&amp;rsquo;s assume it takes 5 minutes to compile the code, and 10 minutes to run the tests.&lt;/p&gt;
&lt;h1 id=&#34;the-slow-development-trap&#34;&gt;The Slow Development Trap&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-slow-development-trap&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Right before your fist public release, you discover that the archive does not contain any README. You then add a single line of code to copy the README file from the sources to the directory used to generate the archive:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  echo &amp;#34;generating archive&amp;#34; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  DESTDIR=/tmp/foo make install
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ cp README /tmp/foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;  cd /tmp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  tar cvfz foo.tar.gz foo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, to see if your code is working, you have to &lt;em&gt;wait the duration of the entire build&lt;/em&gt; before knowing if your code is correct.&lt;/p&gt;
&lt;p&gt;So you wait 20 minutes, and the CI script dies right before generating the archive:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fetching latest changes
compiling ...
runinng tests ...
generting archive ...
cp: cannot stat &amp;#39;README&amp;#39;: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oops, turned out the README was called &lt;code&gt;README.md&lt;/code&gt; and not just &lt;code&gt;README&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So you make an other change:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- cp README /tmp/foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ cp README.md /tmp/foo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You wait an other 20 minutes, and the build passes again.&lt;/p&gt;
&lt;p&gt;Congrats, you just &lt;em&gt;spent 40 minutes making a one-line patch (!)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s what I call &amp;ldquo;The Slow Development Trap&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;But wait, it gets worse.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s keep our simplistic example and study a few bugs you may encounter.&lt;/p&gt;
&lt;h1 id=&#34;ci-bugs-and-where-to-find-them&#34;&gt;CI bugs and where to find them&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#ci-bugs-and-where-to-find-them&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&#34;the-fatal-typo&#34;&gt;The fatal typo&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-fatal-typo&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/geek-and-poke-its-normal.png&#34; alt=&#34;All the automated tests have crashed - it&amp;rsquo;s normal&#34;&gt;&lt;/p&gt;
&lt;p&gt;First example: the script always crashes right before running any test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiling&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;running tests&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make tests
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;make: *** No rule to make target &amp;#39;tests&amp;#39;.  Stop.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Got it? The Makefile target is called &lt;code&gt;test&lt;/code&gt;, singular, not &lt;code&gt;tests&lt;/code&gt;, plural.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re lucky, your team mates will wait until you fix the problem, but some may be entitled to by-pass CI completely because &amp;ldquo;we have run all the tests on our machines before running &lt;code&gt;git push&lt;/code&gt; like we always do&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Hint: they didn&amp;rsquo;t. No one ever does that &lt;em&gt;all the time&lt;/em&gt;, and it&amp;rsquo;s the very reason we use CI in the first place. So better hurry before the master branch is full of failing tests. And remember the Slow Development Trap.&lt;/p&gt;
&lt;h1 id=&#34;forgetting-something-important&#34;&gt;Forgetting something important&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#forgetting-something-important&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Second example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;fetching latest changes&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git reset --hard @{u}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiling&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;echo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;running tests&amp;#34;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;make &lt;span style=&#34;color:#24909d&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Your forgot to call &lt;code&gt;git fetch&lt;/code&gt;. The logs look like the code was updated, but in reality you just keep resetting the working tree to the same commit.
Since this was a good commit, all the tests always pass.&lt;/p&gt;
&lt;p&gt;A week later you find several bugs have been introduced because the developers wrongly assumed the tests were run on the version of the code they just pushed (and who could blame them?). Also, it&amp;rsquo;s going to take quite some time before the team starts trusting the CI scripts again. &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h1 id=&#34;un-seul-être-vous-manque-&#34;&gt;Un seul être vous manque &amp;hellip;&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#un-seul-%c3%aatre-vous-manque-&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Third example: You are building a Qt application and in the Makefile you use to install, the rule to copy &lt;code&gt;libQt5Widgets.so&lt;/code&gt; is missing.&lt;/p&gt;
&lt;p&gt;The main program then crashes horribly the first time it is run right after installation.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error while loading shared libraries: libQt5Widgets.so.5:
cannot open shared object file: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This means that you can no longer ship, you can no longer do QA, and everyone gets stuck until you fix the bug (and we&amp;rsquo;re back to &amp;lsquo;development is slow&amp;rsquo;)&lt;/p&gt;
&lt;p&gt;By now you should have realized that &lt;strong&gt;you are not allowed to have bugs in your CI scripts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Scared much? Let&amp;rsquo;s talk about time travel for a change.&lt;/p&gt;
&lt;h1 id=&#34;back-to-the-future&#34;&gt;Back to the future&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#back-to-the-future&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Your team is working on a brand new product they intent to release in two months. You start writing CI scripts right away. But you still have to travel to the future and make sure the scripts you wrote today still work. Or at least, you can make them work quickly. Remember: &amp;ldquo;no bugs allowed&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;So, in addition to not be allowed to have any bugs, you &lt;em&gt;also&lt;/em&gt; have to &lt;strong&gt;implement all the required features&lt;/strong&gt; and you &lt;strong&gt;cannot miss the deadline&lt;/strong&gt;. If you&amp;rsquo;re late, you can&amp;rsquo;t ship. Or worse, you&amp;rsquo;ll ship by doing the required steps by hand, and then you&amp;rsquo;ll get an whole new set of problems.&lt;/p&gt;
&lt;h1 id=&#34;forward-from-the-past&#34;&gt;Forward from the past&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#forward-from-the-past&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Two years ago you released version 2.5.2 of your flagship product, the last of the 2.x series.&lt;/p&gt;
&lt;p&gt;Since then you made some pretty big redesigns, and released version 3.0 and 3.1. Most of your clients have made the switch, developers are happy to no longer have to work on the ancient code base, everything looks OK.&lt;/p&gt;
&lt;p&gt;But then someone sends you an e-mail saying they&amp;rsquo;ve found a security bug in the 2.5.2 release, and they will disclose it next week no matter what.&lt;/p&gt;
&lt;p&gt;Your team spends 1 day discussing and planning a fix. Then they take 3 days to actually implement it, because they have to find their way in an old code base no-one no longer knows very well.  Now it&amp;rsquo;s time to QA the 2.5.3 release.&lt;/p&gt;
&lt;p&gt;Better be sure the scripts you wrote two years ago still work, or everyone will be getting a very hard time!&lt;/p&gt;
&lt;p&gt;OK, enough with scary stories, let&amp;rsquo;s talk about the craft of writing CI code. I&amp;rsquo;m afraid I have some bad news there too.&lt;/p&gt;
&lt;h1 id=&#34;your-standard-approach-will-not-work&#34;&gt;Your standard approach will not work&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#your-standard-approach-will-not-work&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/xkcd-normal-approach.jpg&#34; alt=&#34;my normal approach is useless here&#34;&gt;&lt;/p&gt;
&lt;p&gt;Writing CI scripts is very different than writing production code or test code. It&amp;rsquo;s a whole different world. Let me elaborate.&lt;/p&gt;
&lt;h2 id=&#34;testing-is-hard&#34;&gt;Testing is hard&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#testing-is-hard&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Writing automated tests for CI scripts is difficult and almost never catch any bugs (at least, based on my experience). The best way to check that a CI script works is by running it it its entirety. And then you fall yet again into the Slow Development Trap.&lt;/p&gt;
&lt;h2 id=&#34;debug-is-hard&#34;&gt;Debug is hard&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#debug-is-hard&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;CI scripts are hard to debug because they usually don&amp;rsquo;t run on developer&amp;rsquo;s machine but on runners where debug tools are seldom found.&lt;/p&gt;
&lt;p&gt;If the worst case scenario (which happens quite often), your only option will be to add debug logs and this means getting caught by The Slow Development Trap all over again.&lt;/p&gt;
&lt;h1 id=&#34;eliminating-fear&#34;&gt;Eliminating fear&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#eliminating-fear&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;By now you should start getting nervous.&lt;/p&gt;
&lt;p&gt;TDD helped &lt;em&gt;me&lt;/em&gt; getting rid of the fear of changing production code by teaching me a way of writing tests and production code in a nice loop that often leads to code that has a high quality and few defects.&lt;/p&gt;
&lt;p&gt;For this series, I will be trying to do the same thing. I&amp;rsquo;ll tell you how to resist the Slow Development Trap, and how to avoid the bugs we discussed (and many others). Hopefully next time you&amp;rsquo;ll have to change a CI script it will be less scary.&lt;/p&gt;
&lt;p&gt;See you next time, where we&amp;rsquo;ll introduce a few useful concepts.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I&amp;rsquo;m not going to give you proofs of these events because they&amp;rsquo;re quite embarrassing for everyone involved.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;That happened to me by the way: &lt;em&gt;I&lt;/em&gt; was the guy who forgot to fetch.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Introducing &#34;Tips From a Build Farmer&#34;</title>
      <link>https://dmerej.info/blog/post/introducing-tips-from-a-build-farmer/</link>
      <pubDate>Sat, 18 Aug 2018 08:34:50 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/introducing-tips-from-a-build-farmer/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve spent several years working on CI scripts and infrastructure. I&amp;rsquo;ve used many tools (Jenkins, Travis, GitLab CI, &amp;hellip;). I&amp;rsquo;ve made a lot of mistakes, and I learned a few things I thought I might share here.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the list of articles published so far in these series:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/tips-from-a-build-farmer-part-1-ci-scripts-are-scary/&#34;&gt;Part 1: CI scripts are scary&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/tips-from-a-build-farmer-part-2-some-concepts/&#34;&gt;Part 2: Some concepts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: This series has been canceled. I am &lt;a href=&#34;https://dmerej.info/blog/post/im-writing-a-book/&#34;&gt;writing a book&lt;/a&gt; instead!&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Hello flake8</title>
      <link>https://dmerej.info/blog/post/hello-flake8/</link>
      <pubDate>Mon, 13 Aug 2018 14:12:44 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/hello-flake8/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;In my &lt;a href=&#34;https://dmerej.info/blog/post/bye-bye-pylint/&#34;&gt;last article&lt;/a&gt; I explained why I decided to no longer use pylint.&lt;/p&gt;
&lt;p&gt;In a nutshell, most pylint warning are now caught by other linters, and all that&amp;rsquo;s left are
some warnings.&lt;/p&gt;
&lt;p&gt;In an &lt;a href=&#34;https://dmerej.info/blog/post/how-i-lint/#putting-it-all-together&#34;&gt;other article&lt;/a&gt; I mentioned &lt;a href=&#34;http://flake8.pycqa.org/en/latest/&#34;&gt;flake8&lt;/a&gt; briefly, saying that I preferred a simple bash script to drive the execution of the various linters.&lt;/p&gt;
&lt;p&gt;I was concerned that flake8 did not include pylint (now I no longer care of course). Also, I did not like the fact that flake8 forces a specific version for all the linters it runs.&lt;/p&gt;
&lt;p&gt;Well, I was wrong (again).&lt;/p&gt;
&lt;h1 id=&#34;flake8-is-awesome&#34;&gt;flake8 is awesome&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#flake8-is-awesome&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;First off, I thought flake8 only combined the pyflakes and pycodestyle linters and nothing else. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Well, it also includes &lt;a href=&#34;https://pypi.org/project/mccabe/&#34;&gt;mccabe&lt;/a&gt; by default.&lt;/p&gt;
&lt;p&gt;Also, as explained in the &lt;a href=&#34;http://flake8.pycqa.org/en/latest/faq.html#why-does-flake8-use-ranges-for-its-dependencies&#34;&gt;FAQ&lt;/a&gt;, there are significant advantages in having the versions of the linters frozen this way.&lt;/p&gt;
&lt;p&gt;Here are some other features I overlooked:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can use the &lt;code&gt;setup.cfg&lt;/code&gt; file to configure all the linters flake8 knows about&lt;/li&gt;
&lt;li&gt;The output is consistent for all the linters&lt;/li&gt;
&lt;li&gt;The checks of any linter can be be disabled on any line with just a &lt;code&gt;# noqa&lt;/code&gt; comment&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;a-nice-surprise&#34;&gt;A nice surprise&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-nice-surprise&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The last time I upgraded pylint, I only got one new warning. It was on a line looking like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;my_set = &lt;span style=&#34;color:#24909d&#34;&gt;set&lt;/span&gt;([elem &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; elem &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; my_list &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; some_condition(elem)])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The intent here is to build a unique set from a list of elements that satisfy a given condition.&lt;/p&gt;
&lt;p&gt;pylint emitted the following warning:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;R1718: Consider using a set comprehension (consider-using-set-comprehension)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Indeed, the code can also be written like this, using a &lt;em&gt;set comprehension&lt;/em&gt; instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;my_set = {elem &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; elem &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; my_list &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; some_condition(elem)}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The code is shorter&lt;/li&gt;
&lt;li&gt;We no longer build a list (inside the  square brackets) just to throw it immediately afterwards&lt;/li&gt;
&lt;li&gt;The interpreter does not have to look up the &lt;code&gt;set()&lt;/code&gt; function, so the code is faster&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well, there is already a flake8 plugin called &lt;a href=&#34;https://pypi.org/project/flake8-comprehensions/&#34;&gt;flake8-comprehension&lt;/a&gt; that deals with these kind of issues.&lt;/p&gt;
&lt;p&gt;In fact, &lt;a href=&#34;https://pypi.org/search/?q=flake8-&#34;&gt;there are a bunch of flake8 plugins&lt;/a&gt; available!&lt;/p&gt;
&lt;p&gt;Plus, adding a new flake8 plugin is as easy as running &lt;code&gt;pipenv install --dev &amp;lt;plugin name&amp;gt;&lt;/code&gt; and nothing else has to change :)&lt;/p&gt;
&lt;h1 id=&#34;the-future-is-bright&#34;&gt;The future is bright&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-future-is-bright&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Itamar Turner-Trauring &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, in the &lt;a href=&#34;https://dev.to/dmerejkowsky/bye-bye-pylint-4chh&#34;&gt;comment section&lt;/a&gt; on dev.to gave an interesting example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Note: I&amp;#39;ve taken the liberty of making the code a bit less abstract&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;greet&lt;/span&gt;(prefix, name):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(prefix, name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;greeters = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;prefixes = [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Howdy&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; prefix &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; prefixes:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    greeters.append(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;lambda&lt;/span&gt; x: greet(prefix, x))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; greeter &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; greeters:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    greeter(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may think the following code would print:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Hi world
Hello world
Howdy world
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;but instead it prints:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Howdy world
Howdy world
Howdy world
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This has to do with how the closures work in Python, and the bug is indeed caught by pylint:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pylint example.py
 W0640: Cell variable `prefix` defined in loop (cell-var-from-loop)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I did not find a flake8 plugin that could catch this bug right away, but I found &lt;a href=&#34;https://github.com/PyCQA/flake8-bugbear&#34;&gt;flake8-bugbear&lt;/a&gt;, a plugin to &amp;ldquo;find likely bugs and design problems&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The plugin is well-written, well-tested and easy to contribute to.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve already tried &lt;a href=&#34;https://github.com/PyCQA/flake8-bugbear/pull/51&#34;&gt;porting some pylint warnings to  flake8-bugbear&lt;/a&gt; and so far it has been much easier than I thought. &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Therefore, next time I find a bug that could have been caught by inspecting the AST (which is what both flake8-bugbear and pylint do), I know how to write or contribute to a flake8 plugin in order to automatically catch it during CI.&lt;/p&gt;
&lt;p&gt;Thus, I can slowly build a complete replacement for pylint, with just the warnings I care about, and without the configuration issues and false positives.&lt;/p&gt;
&lt;p&gt;Bright future indeed!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;The name of the project is somewhat misleading.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;If you haven&amp;rsquo;t already, you should definitively check &lt;a href=&#34;https://codewithoutrules.com/&#34;&gt;his blog&lt;/a&gt; and subscribe to the &lt;em&gt;Software Clown&lt;/em&gt; mailing list.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Note that the pull request was actually not merged. In reality, I started by blindly adding a new check in flake8 &lt;em&gt;before&lt;/em&gt; taking a look at the whole list of flake8 plugins. The pull request got closed because it turned out the check I added was already in the &lt;code&gt;flake8-comprehensions&lt;/code&gt; plugin. Sometimes you have to lie to make a better story &amp;hellip;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Je cherche une asso</title>
      <link>https://dmerej.info/blog/post/je-cherche-une-asso/</link>
      <pubDate>Thu, 09 Aug 2018 17:31:47 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/je-cherche-une-asso/</guid>
      <description>&lt;p&gt;&lt;em&gt;Mise à jour: J&amp;rsquo;ai trouvé :) Je donne dorénavant un cours sur Python  un samedi sur 2 à &lt;a href=&#34;https://www.e2li.org/&#34;&gt;l&amp;rsquo;École du Logiciel Libre&lt;/a&gt;. Merci à tous ceux qui m&amp;rsquo;ont répondu et ont fait circuler ce message!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Bonjour chers lecteurs!&lt;/p&gt;
&lt;p&gt;Un article un peu spécial aujourd&amp;rsquo;hui, en Français pour changer.&lt;/p&gt;
&lt;p&gt;Comme vous le savez sans doute si vous êtes un lecteur régulier ou si vous m&amp;rsquo;avez déjà croisé, j&amp;rsquo;adore le langage Python. Vous savez aussi que j&amp;rsquo;aime partager mes connaissances avec d&amp;rsquo;autres.&lt;/p&gt;
&lt;p&gt;Je cherche donc une association (ou un cadre similaire) où je pourrais donner des formations dans ce langage, par exemple en tant que bénévole.&lt;/p&gt;
&lt;h2 id=&#34;quelques-informations&#34;&gt;Quelques informations&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#quelques-informations&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;J&amp;rsquo;habite à Paris, donc idéalement il faudrait des formations pas trop loin.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;J&amp;rsquo;ai déjà donné pas mal de conférences sur des sujets divers, que ce soit dans des salons ou pour mes collègues de travail. Je suis également mentor sur &lt;a href=&#34;https://exercism.io/&#34;&gt;exercism.io&lt;/a&gt; où j&amp;rsquo;aide régulièrement des débutants dans leur découverte du langage en relisant et commentant leurs solutions à des exercices variés.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Je suis toujours employé en tant que développeur et compte le rester, donc je ne pourrai pas être formateur à temps plein, mais je suis disponible ponctuellement ou quelques heures par semaine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Je me sens capable de donner des cours à la fois pour des débutants complets (en utilisant Python pour une introduction générale à la programmation), ou sur des sujets précis comme porter du code de Python2 à Python3, des sujets autour de Django, Flask, les tests, le refactoring, etc &amp;hellip;).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bien sûr, tout ceci est négociable!&lt;/p&gt;
&lt;h2 id=&#34;une-bouteille-à-la-mer&#34;&gt;Une bouteille à la mer&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#une-bouteille-%c3%a0-la-mer&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Si vous connaissez une association qui convienne ou semblable, que vous souhaitez me poser plus de questions, ou si vous avez d&amp;rsquo;autres pistes à me conseiller, vous pouvez me contacter de plein de façons, qui sont toutes listées sur &lt;a href=&#34;https://dmerej.info/blog/pages/contact/&#34;&gt;ma page de contact&lt;/a&gt;, ou simplement laisser un commentaire ci-dessous.&lt;/p&gt;
&lt;p&gt;Si le cœur vous en dit, vous pouvez aussi faire circuler ce message autour de vous.&lt;/p&gt;
&lt;p&gt;Comme d&amp;rsquo;habitude, merci de m&amp;rsquo;avoir lu jusqu&amp;rsquo;au bout et à la prochaine!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Bye-bye pylint</title>
      <link>https://dmerej.info/blog/post/bye-bye-pylint/</link>
      <pubDate>Tue, 07 Aug 2018 17:23:02 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/bye-bye-pylint/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been using &lt;a href=&#34;https://www.pylint.org/&#34;&gt;pylint&lt;/a&gt; for almost a decade now.&lt;/p&gt;
&lt;p&gt;Fast-forward ten years later, and I&amp;rsquo;ve decided no longer use it.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s why.&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s start with an example. Consider the following, obviously incorrect code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;foo&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; __name__ == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foo(&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#3677a9&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#3677a9&#34;&gt;3&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s what the output of pylint might look like when you run it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pylint foo.py
foo.py:4: [E1121(too-many-function-args), ]
  Too many positional arguments for function call
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let&amp;rsquo;s see a few problems I&amp;rsquo;ve encountered while using pylint.&lt;/p&gt;
&lt;h1 id=&#34;pain-points&#34;&gt;Pain points&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#pain-points&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&#34;initial-setup&#34;&gt;Initial setup&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#initial-setup&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Initial setup of pylint is always a bit painful. However, if you follow &lt;a href=&#34;https://dmerej.info/blog/post/some-pylint-tips/&#34;&gt;some advice&lt;/a&gt; you can get through it.&lt;/p&gt;
&lt;h2 id=&#34;false-positives&#34;&gt;False positives&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#false-positives&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A recurring issue with pylint is the amount of false positives. That is, when pylint thinks something is wrong but the code is perfectly OK.&lt;/p&gt;
&lt;p&gt;For instance, I like using the &lt;a href=&#34;http://www.attrs.org/en/stable/overview.html&#34;&gt;attrs&lt;/a&gt; library whenever I have a class that mostly contains data, like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;attr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ffa500&#34;&gt;@attr.s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Foo&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bar = attr.ib()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    baz = attr.ib()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Those few lines of code give me a nice human-readable &lt;code&gt;__repr__&lt;/code&gt;, a complete set of comparison methods, sensible constructors (among other things), and without any boiler plate.&lt;/p&gt;
&lt;p&gt;But when I run pylint on this file I get:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;foo.py:3: [R0903(too-few-public-methods), Foo] Too few public methods (0/2)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well, it&amp;rsquo;s perfectly fine to require at least 2 public methods for every class you declare. Most of the time, when you have a class with just &lt;em&gt;one&lt;/em&gt; public method it&amp;rsquo;s better to just have a function instead, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# What you wrote:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Greeter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, name=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._name = name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;greet&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;, self.name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# What you should have written instead:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;greet&lt;/span&gt;(name=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt; , name)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But here pylint does not know about all the nice methods added &amp;ldquo;dynamically&amp;rdquo; by &lt;code&gt;attr&lt;/code&gt; and wrongly assumes our design is wrong.&lt;/p&gt;
&lt;p&gt;Thus, if you run pylint during CI and you fail the build if any error is found, you have to insert a specially formatted comment to locally disable this warning:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;attr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# pylint: disable=too-few-public-methods&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ffa500&#34;&gt;@attr.s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Foo&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gets old fast, especially because every time you upgrade pylint you get a new bunch of checks added. Sometimes they catch new problems in your code, but you still have to go through each and every new error to check if it&amp;rsquo;s a false positive or a real issue.&lt;/p&gt;
&lt;p&gt;But so far I had managed to overcome those pain points. So what changed?&lt;/p&gt;
&lt;h1 id=&#34;turning-the-page&#34;&gt;Turning the page&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#turning-the-page&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Two things happened:&lt;/p&gt;
&lt;p&gt;First, I&amp;rsquo;ve &lt;a href=&#34;https://dmerej.info/blog/post/giving-mypy-a-go/&#34;&gt;started using mypy&lt;/a&gt; and a &amp;ldquo;real&amp;rdquo; type system &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;What I found is that mypy can catch many of the errors pylint would catch, and probably more.&lt;/p&gt;
&lt;p&gt;Also, since it uses type annotations mypy is both faster and more precise than pylint (because it does not have to &amp;ldquo;guess&amp;rdquo; anything).&lt;/p&gt;
&lt;p&gt;Last but not least, mypy was also designed to be used &lt;em&gt;gradually&lt;/em&gt;, emitting errors only when it is &lt;em&gt;sure&lt;/em&gt; there&amp;rsquo;s something wrong.&lt;/p&gt;
&lt;p&gt;Secondly, I decided to port one of my projects to Python3.7. I had to bump pylint from 1.9 to 2.1 (because older pylint versions do not support Python3.7), and I got 18 new pylint errors, which only &lt;em&gt;one&lt;/em&gt; of them being actually relevant.&lt;/p&gt;
&lt;p&gt;It was at this moment I decided to take a step back.&lt;/p&gt;
&lt;h1 id=&#34;categories&#34;&gt;Categories&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#categories&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;As we saw in those examples, the pylint error messages contain a short name for the error (like &lt;code&gt;too-many-function-args&lt;/code&gt;), and an numeric ID prefixed by a letter (&lt;code&gt;E1121&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Each letter corresponds to a pylint &lt;em&gt;category&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here is a complete list:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(&lt;em&gt;F&lt;/em&gt;)atal (something prevented pylint from running normally)&lt;/li&gt;
&lt;li&gt;(&lt;em&gt;E&lt;/em&gt;)rror (serious bug)&lt;/li&gt;
&lt;li&gt;(&lt;em&gt;W&lt;/em&gt;)arning (not so serious issue)&lt;/li&gt;
&lt;li&gt;(&lt;em&gt;I&lt;/em&gt;)nfo (errors like being unable to parse a &lt;code&gt;# pylint: disable&lt;/code&gt; comment)&lt;/li&gt;
&lt;li&gt;(&lt;em&gt;C&lt;/em&gt;)onvention (coding style)&lt;/li&gt;
&lt;li&gt;(&lt;em&gt;R&lt;/em&gt;)efactoring (code that could be written in a clearer or more Pythonic way)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that &lt;em&gt;Fatal&lt;/em&gt; and &lt;em&gt;Info&lt;/em&gt; categories are only useful when we try to understand why pylint does not behave the way it should.&lt;/p&gt;
&lt;h1 id=&#34;the-rise-of-the-linters&#34;&gt;The rise of the linters&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-rise-of-the-linters&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I realized I could use other linters (not just mypy) for almost every pylint category.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some of the &lt;em&gt;Error&lt;/em&gt; messages can also be caught by &lt;a href=&#34;https://pypi.org/project/pyflakes/&#34;&gt;pyflakes&lt;/a&gt; which is fast and produces very few false positive too.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;Convention&lt;/em&gt; category can also be taken care of by &lt;a href=&#34;https://pycodestyle.readthedocs.io/en/latest/&#34;&gt;pycodestyle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A few &lt;em&gt;Refactoring&lt;/em&gt; warnings (but not all) can also be caught by &lt;a href=&#34;https://pypi.org/project/mccabe/&#34;&gt;mccabe&lt;/a&gt;, which measures code complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So far I&amp;rsquo;ve been using all theses linters in &lt;em&gt;addition&lt;/em&gt; to pylint, as explained in &lt;a href=&#34;https://dmerej.info/blog/post/how-i-lint/&#34;&gt;how I lint my Python&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But what if I stopped using pylint altogether?&lt;/p&gt;
&lt;p&gt;All I would lose would be some of the &lt;em&gt;Refactoring&lt;/em&gt; messages, but I assumed most of them would get caught during code review. In exchange, I could get rid of all these noisy &lt;code&gt;# pylint: disable&lt;/code&gt; comments. (34 of them for about 5,000 lines of code)&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s how I stopped using pylint and removed it from my CI scripts. My apologies to pylint authors and maintainers: you did a really great job all these years, but I now believe it&amp;rsquo;s time for me to move on and use new and better tools instead.&lt;/p&gt;
&lt;h1 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#whats-next&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is not the end of the story of my never-ending quest of tools to help me write better Python code. You can read the rest of the story in &lt;a href=&#34;https://dmerej.info/blog/post/hello-flake8/&#34;&gt;Hello flake8&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;By the way, at the end of  &lt;em&gt;&lt;a href=&#34;https://dmerej.info/blog/post/giving-mypy-a-go/&#34;&gt;Giving mypy a go&lt;/a&gt;&lt;/em&gt; I said I was curious to know if mypy would help during &lt;a href=&#34;https://github.com/dmerejkowsky/tbump/pull/24/files&#34;&gt;a massive refactoring&lt;/a&gt;. Well, it did, even better than I would have hoped!&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>Please verify your email on pypi.org and test.pypi.org</title>
      <link>https://dmerej.info/blog/post/please-verify-your-email-on-pypiorg-and-testpypiorg/</link>
      <pubDate>Tue, 17 Jul 2018 20:52:02 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/please-verify-your-email-on-pypiorg-and-testpypiorg/</guid>
      <description>&lt;p&gt;Just a quick post to kindly ask you to make sure your email is verified on both pypi.org and test.pypi.org&lt;/p&gt;
&lt;h1 id=&#34;what-to-do&#34;&gt;What to do&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#what-to-do&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Ff you have an account on either pypi.org or test.pypi.org, please make sure that you email is verified, and if not, ask for a confirmation email to be sent.&lt;/p&gt;
&lt;p&gt;Whether or not you have an account, feel free to spread the news using those links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/thepypa/status/1019040253020123137&#34;&gt;announce on twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mail.python.org/mm3/archives/list/distutils-sig@python.org/message/5ER2YET54CSX4FV2VP24JA57REDDW5OI/&#34;&gt;announce on distutils-sig@python.org&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also re-use this article on your own blog for instance ;) &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h1 id=&#34;why-this-matters&#34;&gt;Why this matters&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#why-this-matters&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;pypi.org is essential to lots of python developers, but is unfortunately maintained by a tiny number of great people and they need our help.&lt;/p&gt;
&lt;p&gt;If we don’t help them, pypi.org may become unable to send &lt;em&gt;any&lt;/em&gt; email, period, which will make things really complicated for everyone.&lt;/p&gt;
&lt;h1 id=&#34;more-details&#34;&gt;More details&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#more-details&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The full explanation is also &lt;a href=&#34;https://github.com/pypa/warehouse/issues/3632&#34;&gt;on GitHub&lt;/a&gt; if you want to take a look.&lt;/p&gt;
&lt;p&gt;Thanks for your help in keeping pypi.org working!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Friendly reminder: this article (and all the others on my blog) is licensed or under &lt;a href=&#34;https://creativecommons.org/licenses/by/4.0/&#34;&gt;a very permissive Creative Commons CC-by license&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Else after return: yea or nay?</title>
      <link>https://dmerej.info/blog/post/else-after-return-yea-or-nay/</link>
      <pubDate>Thu, 12 Jul 2018 15:38:15 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/else-after-return-yea-or-nay/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;As you may know, I use &lt;a href=&#34;https://www.pylint.org/&#34;&gt;pylint&lt;/a&gt; for most of my Python projects.&lt;/p&gt;
&lt;p&gt;A few weeks ago, I upgraded pylint and a new warning appeared. This tends to happen when you have a pretty large code base: new checks are added to pylint all the time, so new warnings are bound to show up.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a minimal example of the kind of code that triggered the new warning:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;foo&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; bar:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; baz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; qux
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pylint foo.py
...
Unnecessary &amp;#34;else&amp;#34; after &amp;#34;return&amp;#34; (no-else-return)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Indeed, the code after the first return will never execute if &lt;code&gt;bar&lt;/code&gt; is true, so there&amp;rsquo;s no need for the &lt;code&gt;else&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In other words, the code should be written like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;foo&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; bar:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; baz
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; qux
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, the code is shorter. But is it &lt;em&gt;better&lt;/em&gt;?&lt;/p&gt;
&lt;h1 id=&#34;the-problem&#34;&gt;The problem&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-problem&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;If you think about it, the question about whether the code is &lt;em&gt;better&lt;/em&gt; in the first form (let&amp;rsquo;s call it &lt;em&gt;explicit else&lt;/em&gt;) or in the second form (let&amp;rsquo;s call it &lt;em&gt;implicit else&lt;/em&gt;) is hard to answer because you have no clue about the &lt;em&gt;meaning&lt;/em&gt; of the &lt;code&gt;foo&lt;/code&gt; function, or the &lt;code&gt;bar&lt;/code&gt;, &lt;code&gt;baz&lt;/code&gt; and &lt;code&gt;qux&lt;/code&gt; variables.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s try to come up with better examples.&lt;/p&gt;
&lt;h1 id=&#34;guard-clauses&#34;&gt;Guard clauses&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#guard-clauses&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Sometimes you&amp;rsquo;ll find code written this way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;try_something&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; precondition():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         result = compute_something()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        display_error()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In other words, you are trying to do something but that&amp;rsquo;s only possible if a condition is true. If the condition is false, you need to display an error.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;else&lt;/code&gt; is explicit here.&lt;/p&gt;
&lt;p&gt;The version with an implicit &lt;code&gt;else&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;try_something&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; precondition():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         result = compute_something()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    display_error()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So far, it&amp;rsquo;s not very clear what version is better.&lt;/p&gt;
&lt;p&gt;Note there&amp;rsquo;s a third way to write the same code, by using &lt;code&gt;if not precondition()&lt;/code&gt; instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Implicit else, inverted condition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;try_something&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; precondition():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        display_error()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result = compute_something()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, watch what happens when we add several preconditions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Explicit else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;try_something&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; precondition_one():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; precondition_two():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            result = compute_something()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            display_error_two()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        display_error_one()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Implicit else, inverted condition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;try_something&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; precondition_one():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        display_error_one()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; precondition_two():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        display_error_two()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result = compute_something()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I hope you&amp;rsquo;ll agree the second version is better.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one less level of indentation, and the line that &lt;em&gt;displays&lt;/em&gt; the error is right after the line that &lt;em&gt;checks&lt;/em&gt; for the error.&lt;/p&gt;
&lt;p&gt;Clear win for the &lt;em&gt;implicit else&lt;/em&gt; here.&lt;/p&gt;
&lt;h1 id=&#34;symmetric-conditions&#34;&gt;Symmetric conditions&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#symmetric-conditions&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s take an other example.&lt;/p&gt;
&lt;p&gt;Suppose you are writing a script that will check all the links in documentation written as a set of HTML pages.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve got a list of all the possible pages, and then you need to check both &lt;em&gt;internal links&lt;/em&gt; (with a &lt;code&gt;href&lt;/code&gt; looking  like
&lt;code&gt;../other-page&lt;/code&gt;) and &lt;em&gt;external links&lt;/em&gt; like (with a &lt;code&gt;href&lt;/code&gt; like &lt;code&gt;http://example.com&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at the two variants:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Implicit else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;check_link&lt;/span&gt;(link) -&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;bool&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; is_internal_link(link):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; check_internal_link(link)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; check_external_link(link)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Explicit else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;check_link&lt;/span&gt;(link) -&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;bool&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; is_internal_link(link):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; check_internal_link(link)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; check_external_link(link)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time, I hope you&amp;rsquo;ll agree the explicit else is better.&lt;/p&gt;
&lt;p&gt;There are two things to be done, and visually they are at them at the same level of indentation.&lt;/p&gt;
&lt;p&gt;The symmetry between the type of the link and the check that needs to be done is preserved.&lt;/p&gt;
&lt;p&gt;We could say that the algorithm I&amp;rsquo;ve described as text in the last paragraph is better &lt;em&gt;expressed&lt;/em&gt; in the second version.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Pylint is a great tool, but be careful before deciding whether you want to follow its refactoring pieces of advice.&lt;/p&gt;
&lt;p&gt;Second, make sure your code is &lt;em&gt;easy to read&lt;/em&gt; and &lt;em&gt;reveal your intention&lt;/em&gt;. Conciseness is not the only factor here.&lt;/p&gt;
&lt;p&gt;Last, be careful with code samples that are too abstract :)&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Twitter Timeline Cleaner</title>
      <link>https://dmerej.info/blog/post/twitter-timeline-cleaner/</link>
      <pubDate>Sat, 07 Jul 2018 13:13:13 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/twitter-timeline-cleaner/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this the second post in the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-quantom-of-ideas/&#34;&gt;Quantum of Ideas&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve already explained &lt;a href=&#34;https://dmerej.info/blog/post/twitter-and-me-me-and-twitter/#fixing-my-timeline&#34;&gt;on this blog&lt;/a&gt; why I&amp;rsquo;ve decided to never follow more than 30 accounts on twitter.&lt;/p&gt;
&lt;p&gt;To this day, I&amp;rsquo;m still convinced that if you follow more than 50 accounts, you should seriously considering cleaning your timeline too.&lt;/p&gt;
&lt;p&gt;This may seem like a daunting task, especially if you&amp;rsquo;re already following hundreds of accounts. That&amp;rsquo;s when the Twitter Timeline Cleaner comes in.&lt;/p&gt;
&lt;h1 id=&#34;how-it-works&#34;&gt;How it works&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#how-it-works&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Remember, this is &lt;strong&gt;not&lt;/strong&gt; an existing product, just a &amp;ldquo;work in progress&amp;rdquo; idea.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First, the TTC does a backup of the list of all your followers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then it goes through the list, and for all of account you follow, it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Takes a random sample of recent tweets from this account and asks you to mark them as &lt;em&gt;relevant&lt;/em&gt; or &lt;em&gt;useless&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Then it gives each account a score, something like the average interest of each tweet divided by the frequency of tweets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That way, accounts that tweet rarely but are always interesting get a high score. Accounts that tweet several times per day every day, even if they sometimes have interesting content, get penalized.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When this is done, the TTC shows you a list of accounts sorted by decreasing score, and all you have to do is to select which irrelevant accounts you want to stop following.&lt;/p&gt;
&lt;p&gt;By the way, unless they explicitly configured their account to do so, each account you unfollow will &lt;em&gt;not&lt;/em&gt; get notified, so there&amp;rsquo;s a pretty good chance they won&amp;rsquo;t get mad at you.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: Turns out such a product already exists. Take a look at &lt;a href=&#34;https://www.manageflitter.com/&#34;&gt;https://www.manageflitter.com/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;And that&amp;rsquo;s all there is to it. We could also extend the TTC so that it prevents &lt;em&gt;you&lt;/em&gt; from becoming an account with low signal-to-noise ratio using the same technique. For instance, it would display messages like: &amp;ldquo;only 2% of readers found this tweet interesting&amp;rdquo;, or &amp;ldquo;you&amp;rsquo;ve already tweeted 3 times today, maybe go take a break&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;… or you could just &lt;a href=&#34;https://dmerej.info/blog/post/why-mastodon/&#34;&gt;use Mastodon&lt;/a&gt; where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can choose an instance that matches your interests&lt;/li&gt;
&lt;li&gt;messages are more likely to get interesting due to the 500 characters limit&lt;/li&gt;
&lt;li&gt;discussions are easier to follow because everything is sorted by chronological order&lt;/li&gt;
&lt;li&gt;people are just overall nicer to each other or so it seems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 7: Android and JNA</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-7-android-jna/</link>
      <pubDate>Mon, 18 Jun 2018 12:17:17 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-7-android-jna/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 7 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-6-android-cross-compilation/&#34;&gt;Last time&lt;/a&gt; we managed to cross-compile and run C++ code for Android.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s now time to write some Java code, but we need to take a detour on the desktop first.&lt;/p&gt;
&lt;h1 id=&#34;java-bindings&#34;&gt;Java bindings&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#java-bindings&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s create a new Java library project with &lt;code&gt;gradle&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd chucknorris
$ mkdir java &amp;amp;&amp;amp; cd java
$ gradle init --type java-library
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Gradle created a bunch of files, but for now we just care about the sources and the tests.&lt;/p&gt;
&lt;p&gt;Our goal is to write a test that demonstrates we can indeed get some ChuckNorris facts.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start by removing cruft from the generated &lt;code&gt;build.gradle&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dependencies {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    api &amp;#39;org.apache.commons:commons-math3:3.6.1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    implementation &amp;#39;com.google.guava:guava:23.0&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then let&amp;rsquo;s fix the source files that gradle created so that we have proper package:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ tree java
├── build.gradle
├── gradle
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── chucknorris
    │               └── ChuckNorris.java
    └── test
        └── java
            └── com
                └── chucknorris
                    └── ChuckNorrisTest.java
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we can write a failing test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In ChuckNorrisTest.java */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChuckNorrisTest&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@Test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;testGetFact&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ChuckNorris ck = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; ChuckNorris();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        String fact = ck.&lt;span style=&#34;color:#bbb&#34;&gt;getFact&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        assertThat(fact, containsString(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Chuck Norris&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* In ChuckNorris.java */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChuckNorris&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String &lt;span style=&#34;color:#447fcf&#34;&gt;getFact&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s run the tests:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ./gradlew test
&amp;gt; Task :test FAILED

com.chucknorris.ChuckNorrisTest &amp;gt; testGetFact FAILED
    java.lang.AssertionError at ChuckNorrisTest.java:14

1 test completed, 1 failed

# open build/reports/tests/test/index.html

java.lang.AssertionError:
Expected: a string containing &amp;#34;Chuck Norris&amp;#34;
     but: was &amp;#34;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, this fails for the good reason.&lt;/p&gt;
&lt;p&gt;Now we can try and load our shared library using JNA.&lt;/p&gt;
&lt;p&gt;First, we add the dependency in the &lt;code&gt;build.gradle&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dependencies {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   api &amp;#39;net.java.dev.jna:jna:4.5.1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;    testImplementation &amp;#39;junit:junit:4.12&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we&amp;rsquo;re ready to use JNA:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We use &lt;code&gt;Native.loadLibrary()&lt;/code&gt; to load the shared library&lt;/li&gt;
&lt;li&gt;We create a &lt;code&gt;CLibrary&lt;/code&gt; interface that implements the C functions we want to call as methods. (just &lt;code&gt;chuck_norris_init&lt;/code&gt; for now).&lt;/li&gt;
&lt;li&gt;We call &lt;code&gt;chuck_norris_init&lt;/code&gt; in the constructor of our ChuckNorris class, storing the result into a JNA &lt;code&gt;Pointer&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChuckNorris&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt; Pointer ckPointer;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;static&lt;/span&gt; CLibrary &lt;span style=&#34;color:#447fcf&#34;&gt;loadChuckNorrisLibrary&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; (CLibrary) Native.&lt;span style=&#34;color:#bbb&#34;&gt;loadLibrary&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;chucknorris&amp;#34;&lt;/span&gt;, CLibrary.&lt;span style=&#34;color:#bbb&#34;&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CLibrary&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extends&lt;/span&gt; Library {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CLibrary INSTANCE = loadChuckNorrisLibrary();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;ChuckNorris&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ckPointer = CLibrary.&lt;span style=&#34;color:#bbb&#34;&gt;INSTANCE&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;chuck_norris_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; String &lt;span style=&#34;color:#447fcf&#34;&gt;getFact&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we run the tests:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ./gradlew test
java.lang.UnsatisfiedLinkError: Unable to load library &amp;#39;chucknorris&amp;#39;:
  Native library (linux-x86-64/libchucknorris.so)
  not found in resource path (...)
  at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:303)
  at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:427)
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is expected. We never told JNA where the &lt;code&gt;libchucknorris.so&lt;/code&gt; file is.&lt;/p&gt;
&lt;p&gt;As a reminder, the file currently lives in the &lt;code&gt;build/default&lt;/code&gt; folder. Here&amp;rsquo;s how we built it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ conan install ../..
$ cmake -GNinja -DBUILD_SHARED_LIBS=ON ../..
$ ninja
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are several ways to tell JNA about the location of the shared library file. Here we&amp;rsquo;ll set a system property in the &lt;code&gt;test&lt;/code&gt; block of the Gradle script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gradle&#34; data-lang=&#34;gradle&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; thisFile  = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; File(project.&lt;span style=&#34;color:#bbb&#34;&gt;file&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;build.gradle&amp;#39;&lt;/span&gt;).&lt;span style=&#34;color:#bbb&#34;&gt;absolutePath&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; projectPath = thisFile.&lt;span style=&#34;color:#bbb&#34;&gt;getParentFile&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; topPath = projectPath.&lt;span style=&#34;color:#bbb&#34;&gt;getParentFile&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; cppPath = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; File(topPath, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;cpp&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; cppBuildPath = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; File(cppPath, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build/default/lib&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    systemProperty &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;jna.library.path&amp;#39;&lt;/span&gt;, cppBuildPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if we re-run the tests we get back our first failure:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ./gradlew test

java.lang.AssertionError:
Expected: a string containing &amp;#34;Chuck Norris&amp;#34;
     but: was &amp;#34;&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But we did manage to instantiate the &lt;code&gt;ChuckNorris&lt;/code&gt; class, so this is progress :)&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s implement &lt;code&gt;getFact()&lt;/code&gt;, and while we&amp;rsquo;re at it, add a &lt;code&gt;.close()&lt;/code&gt; method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CLibrary&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extends&lt;/span&gt; Library {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(Pointer pointer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(Pointer pointer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;ChuckNorris&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ckPointer = CLibrary.&lt;span style=&#34;color:#bbb&#34;&gt;INSTANCE&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;chuck_norris_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; String &lt;span style=&#34;color:#447fcf&#34;&gt;getFact&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; CLibrary.&lt;span style=&#34;color:#bbb&#34;&gt;INSTANCE&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(ckPointer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;close&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CLibrary.&lt;span style=&#34;color:#bbb&#34;&gt;INSTANCE&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;chuck_norris_deinit&lt;/span&gt;(ckPointer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Re-run the tests:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ./gradlew test
BUILD SUCCESSFUL
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;h1 id=&#34;creating-a-new-android-project&#34;&gt;Creating a new Android project&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#creating-a-new-android-project&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now we know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to compile the C++ code for Android.&lt;/li&gt;
&lt;li&gt;How to load some C++ in Java, but only for the desktop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s time to glue things together.&lt;/p&gt;
&lt;p&gt;To do so, the best thing is to use Android Studio to create the gradle project, starting with a with a basic activity so we don&amp;rsquo;t have to deal with all the Android boilerplate.&lt;/p&gt;
&lt;h2 id=&#34;adapting-the-gui&#34;&gt;Adapting the GUI&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#adapting-the-gui&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s pretend the ChuckNorris class already exists for now. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;We start by adding a &lt;code&gt;text_view&lt;/code&gt; ID for the text view in the &lt;code&gt;content_main&lt;/code&gt; layout.&lt;/p&gt;
&lt;p&gt;Then we adapt the &lt;code&gt;MainActivity.java&lt;/code&gt; file to  update the text view when clicking on the floating button action:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;MainActivity&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extends&lt;/span&gt; AppCompatActivity {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt; ChuckNorris chuckNorris;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ffa500&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;onCreate&lt;/span&gt;(Bundle savedInstanceState) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chuckNorris = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; ChuckNorris();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;super&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;onCreate&lt;/span&gt;(savedInstanceState);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ffa500&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;onDestroy&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chuckNorris.&lt;span style=&#34;color:#bbb&#34;&gt;close&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;super&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;onDestroy&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;final&lt;/span&gt; TextView textView = (TextView) findViewById(R.&lt;span style=&#34;color:#bbb&#34;&gt;id&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;text_view&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  FloatingActionButton fab = (FloatingActionButton) findViewById(R.&lt;span style=&#34;color:#bbb&#34;&gt;id&lt;/span&gt;.&lt;span style=&#34;color:#bbb&#34;&gt;fab&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fab.&lt;span style=&#34;color:#bbb&#34;&gt;setOnClickListener&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; View.&lt;span style=&#34;color:#bbb&#34;&gt;OnClickListener&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;onClick&lt;/span&gt;(View view) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      String fact = chuckNorris.&lt;span style=&#34;color:#bbb&#34;&gt;getFact&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      textView.&lt;span style=&#34;color:#bbb&#34;&gt;setText&lt;/span&gt;(fact);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  });
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;adding-chucknorris-sources&#34;&gt;Adding ChuckNorris sources&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#adding-chucknorris-sources&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One of Java&amp;rsquo;s slogan is &amp;ldquo;Write Once, Run Everywhere&amp;rdquo; &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add JNA in the dependencies&lt;/li&gt;
&lt;li&gt;Add the ChuckNorris.java file we wrote earlier&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And everything should work, right?&lt;/p&gt;
&lt;h2 id=&#34;fun-with-jnidispatchso&#34;&gt;Fun with jnidispatch.so&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#fun-with-jnidispatchso&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To check if our code works, let&amp;rsquo;s create an emulator, and click on play.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re faced with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ChuckNorris has stopped&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Open App Again&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What? Chuck Norris &lt;em&gt;can&amp;rsquo;t be stopped&lt;/em&gt;, this is unacceptable!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/chuck-norris-punch.gif&#34; alt=&#34;Chuck Norris punching the screen&#34;&gt;&lt;/p&gt;
&lt;p&gt;Time to look at the logs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;06-18 14:27:18.553 6890-6890/info.dmerej.chucknorris E/AndroidRuntime:
FATAL EXCEPTION: main
Process: info.dmerej.chucknorris, PID: 6890
java.lang.UnsatisfiedLinkError:
Native library (com/sun/jna/android-x86-64/libjnidispatch.so)
not found in resource path (.)
  at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath
  at com.sun.jna.Native.loadNativeDispatchLibrary
  ...
  at info.dmerej.chucknorris.ChuckNorris.loadChuckNorrisLibrary
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&amp;rsquo;s a fun one. Turns out the name of dependency &lt;em&gt;changes&lt;/em&gt; when compiling for Android, you need a &lt;code&gt;@aar&lt;/code&gt; prefix &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gradle&#34; data-lang=&#34;gradle&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dependencies {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  implementation &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;net.java.dev.jna:jna:4.5.1@aar&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try again!&lt;/p&gt;
&lt;p&gt;We get the same error message, but this time it&amp;rsquo;s the &lt;code&gt;chucknorris.so&lt;/code&gt; library that is not found:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;06-18 14:27:18.553 6890-6890/info.dmerej.chucknorris E/AndroidRuntime:
FATAL EXCEPTION: main
Process: info.dmerej.chucknorris, PID: 6890
java.lang.UnsatisfiedLinkError: Unable to load library &amp;#39;chucknorris&amp;#39;:
  Native library (android-x86-64/libchucknorris.so) not found
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Fortunately, there&amp;rsquo;s a more or less standard solution.&lt;/p&gt;
&lt;p&gt;If you put a &lt;code&gt;.so&lt;/code&gt; file in a folder named &lt;code&gt;src/main/jniLibs/&amp;lt;arch&amp;gt;&lt;/code&gt;, it will be included inside the Java application, and the Java code will be able to load it without any configuration.&lt;/p&gt;
&lt;h2 id=&#34;the-shared-option&#34;&gt;The shared option&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-shared-option&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For simplicity purposes, we built the ChuckNorris library as a static library, just to show that the C++ binary still needed &lt;code&gt;libc++_shared.so&lt;/code&gt; to run.
But JNA needs a shared library to run.&lt;/p&gt;
&lt;p&gt;Remember in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/&#34;&gt;part 4&lt;/a&gt; we had to call CMake with &lt;code&gt;-DBUILD_SHARED_LIBS=ON&lt;/code&gt; to get a shared library.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll do the same thing, but going through Conan this time.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s add the &lt;code&gt;ChuckNorris:shared&lt;/code&gt; option in the &lt;code&gt;android&lt;/code&gt; profile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[options]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;*:pic&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;ChuckNorris:shared&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then adapt the recipe:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChucknorrisConan&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ChuckNorris&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;    options = {&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;    default_options = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shared=False&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;build&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake = CMake(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        cmake_definitions = {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.options.shared:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;            cmake_definitions[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;BUILD_SHARED_LIBS&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        cmake.configure(defs=cmake_definitions)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/libchucknorris.so&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;        self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/libc++_shared.so&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then let&amp;rsquo;s re-create the Conan package:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan create . dmerej/test --profile android --setting arch=x86_64
Exporting package recipe
...
package(): Copied 2 &amp;#39;.so&amp;#39; files: libchucknorris.so, libc++_shared.so
Package &amp;#39;&amp;lt;hash&amp;gt;&amp;#39; created
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally let&amp;rsquo;s create symlinks to all &lt;code&gt;.so&lt;/code&gt; files from the package.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd android/app
$ cd src/main
$ mkdir -p jniLibs/x86_64
$ cd jniLibs/x86_64
$ ln -s ~/.conan/data/ChuckNorris/0.1/dmerej/test/&amp;lt;hash&amp;gt;/libchucknorris.so .
$ ln -s ~/.conan/data/ChuckNorris/0.1/dmerej/test/&amp;lt;hash&amp;gt;/libc++_shared.so .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s try again:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/chuck-norris-android.png&#34; alt=&#34;Chuck Norris app running&#34;&gt;&lt;/p&gt;
&lt;p&gt;Victory \o/&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for today. See you next time!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;This is also known as &lt;a href=&#34;https://dev.to/_bigblind/quick-tip-programming-by-wishful-thinking-3hn&#34;&gt;wishful thinking programming&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;As always, the &lt;a href=&#34;https://en.wikipedia.org/wiki/Write_once,_run_anywhere&#34;&gt;Wikipedia page&lt;/a&gt; contains lots of interesting stuff about this topic.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;You can find a note about this in &lt;a href=&#34;https://github.com/java-native-access/jna/blob/master/www/FrequentlyAskedQuestions.md#jna-on-android&#34;&gt;JNA&amp;rsquo;s FAQ&lt;/a&gt;, but as far as I know, not &lt;em&gt;anywhere else&lt;/em&gt; in the documentation.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Giving mypy a go</title>
      <link>https://dmerej.info/blog/post/giving-mypy-a-go/</link>
      <pubDate>Mon, 11 Jun 2018 10:17:17 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/giving-mypy-a-go/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is a follow up to the &lt;a href=&#34;https://dmerej.info/blog/post/i-dont-need-types/&#34;&gt;I don&amp;rsquo;t need types&lt;/a&gt; article.&lt;/p&gt;
&lt;p&gt;I left a teaser explaining I&amp;rsquo;ll be giving concrete examples using a Python project, so here goes.&lt;/p&gt;
&lt;p&gt;As you may have guessed, I&amp;rsquo;m going to talk about type annotations and the &lt;a href=&#34;http://mypy-lang.org/&#34;&gt;mypy&lt;/a&gt; static type checker.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: 2021-11-15: Feel free to also read the &lt;a href=&#34;https://sethmlarson.dev/blog/2021-10-18/tests-arent-enough-case-study-after-adding-types-to-urllib3&#34;&gt;case study about urllib3&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;how-mypy-works&#34;&gt;How mypy works&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#how-mypy-works&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s a quick overview of how mypy works, in case you are not already familiar with it.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use a rather contrived example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;is_odd&lt;/span&gt;(num):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; num % &lt;span style=&#34;color:#3677a9&#34;&gt;2&lt;/span&gt; == &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; is_odd(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;this sentence contains &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have a function &lt;code&gt;is_odd&lt;/code&gt;, which obviously only works with numbers, and we call it with a string.&lt;/p&gt;
&lt;p&gt;But since the string contains &lt;code&gt;%s&lt;/code&gt;, Python will happily assume we are trying to format it, and the bug will go unnoticed.
&lt;code&gt;is_odd&lt;/code&gt; will simply return False, because we are &lt;em&gt;also&lt;/em&gt; allowed to compare strings and numbers with &lt;code&gt;==&lt;/code&gt; in Python.&lt;/p&gt;
&lt;p&gt;Without type annotations, mypy detects nothing:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ mypy foo.py
&amp;lt;nothing&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But if we add type annotations and re-run mypy, we do get an error message:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;is_odd&lt;/span&gt;(num: &lt;span style=&#34;color:#24909d&#34;&gt;int&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;bool&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; num % &lt;span style=&#34;color:#3677a9&#34;&gt;2&lt;/span&gt; == &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; is_odd(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;this sentence contains &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ mypy foo.py
error: Argument 1 to &amp;#34;is_odd&amp;#34; has incompatible type &amp;#34;str&amp;#34;; expected &amp;#34;int&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Thus, you can use mypy in a loop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start by annotating a few functions.&lt;/li&gt;
&lt;li&gt;Run mypy on your source code.&lt;/li&gt;
&lt;li&gt;If it detects some errors, either fix the annotations or the code.&lt;/li&gt;
&lt;li&gt;Back to step one&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is called &amp;ldquo;gradual typing&amp;rdquo;.&lt;/p&gt;
&lt;h1 id=&#34;designing-an-experiment&#34;&gt;Designing an experiment&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#designing-an-experiment&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The goal of the experiment is to check if going through the trouble of adding type annotations is worth it.&lt;/p&gt;
&lt;h2 id=&#34;some-definitions&#34;&gt;Some definitions&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#some-definitions&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let me define what I mean by &amp;ldquo;worth it&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;There are many things said about types annotations like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It makes it easier for external contributors to understand the code&lt;/li&gt;
&lt;li&gt;It helps during refactorings&lt;/li&gt;
&lt;li&gt;It facilitates maintenance of large projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those may be true, but they are hard to measure.&lt;/p&gt;
&lt;p&gt;So I asked myself something else:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One: even with everything else (linters, tests, reviews &amp;hellip;), were there bugs that only type annotations would catch?&lt;/li&gt;
&lt;li&gt;Two: were the changes required to have mypy run without errors improving the quality of the code?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know the second question is a bit subjective. I&amp;rsquo;m still going to use this metric because it&amp;rsquo;s one that really matters to me.&lt;/p&gt;
&lt;h2 id=&#34;choosing-a-project&#34;&gt;Choosing a project&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#choosing-a-project&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To test this hypothesis, I needed an existing project. I used &lt;a href=&#34;https://github.com/dmerejkowsky/tsrc&#34;&gt;tsrc&lt;/a&gt;, the command-line tool we use &lt;a href=&#34;https://tanker.io&#34;&gt;at work&lt;/a&gt; to manage multiple git repositories and automate GitHub and GitLab review automation.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I chose it because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s not too big, so the experiment will not take too long.&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s not too small, so we&amp;rsquo;ll have enough experimental data.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-protocol&#34;&gt;The protocol&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-protocol&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So here is the protocol I used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go through the gradual typing loop until everything is type-annotated.&lt;/li&gt;
&lt;li&gt;Make a note of every non-trivial patch. (That is anything that is &lt;em&gt;not&lt;/em&gt; just adding annotations)&lt;/li&gt;
&lt;li&gt;When the loop is finished, take a look at each of the patch, and ask if a bug was found, and whether it improved the quality of the code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before I continue, I should tell you I used mypy with three important options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--strict&lt;/code&gt;: which means mypy emits an error for &lt;em&gt;every&lt;/em&gt; missing type annotations.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--ignore-missing-imports&lt;/code&gt;: tsrc depends on libraries for which no type stub exist.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--strict-optional&lt;/code&gt;: If you have a string that can None, you must use &lt;code&gt;Optional[str]&lt;/code&gt; instead of just &lt;code&gt;str&lt;/code&gt;. I chose that because:
&lt;ul&gt;
&lt;li&gt;Errors relative to None are quite frequent&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--strict-optional&lt;/code&gt; is going to be the default in a future mypy release.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;looking-at-patches&#34;&gt;Looking at patches&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#looking-at-patches&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s look at trivial patches first:&lt;/p&gt;
&lt;h2 id=&#34;truthy-string&#34;&gt;Truthy string&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#truthy-string&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;find_workspace_path&lt;/span&gt;() -&amp;gt; Path:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    head = os.getcwd()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     tail = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;while&lt;/span&gt; tail:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         tsrc_path = os.path.join(head, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;.tsrc&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; os.path.isdir(tsrc_path):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; Path(head)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             head, tail = os.path.split(head)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; tsrc.Error(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Could not find current workspace&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function starts by checking there is a &lt;code&gt;.tsrc&lt;/code&gt; hidden directory in the working path.
If not, it goes through every parent directory and check if the &lt;code&gt;.tsrc&lt;/code&gt; directory is here. If it reaches the root of the  file system (the second value of &lt;code&gt;os.path.split&lt;/code&gt; is None), it raises an exception.&lt;/p&gt;
&lt;p&gt;mypy did not like that &lt;code&gt;tail&lt;/code&gt; started as a boolean, and then was assigned to a string.&lt;/p&gt;
&lt;p&gt;We can fix that by using a non-empty string, with a value that reveals the intention:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- tail = True
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ tail = &amp;#34;a truthy string&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;     while tail:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An other way would be to use a type like &lt;code&gt;Union[bool,str]&lt;/code&gt; but that would be more confusing I think.&lt;/p&gt;
&lt;p&gt;Anyway, I&amp;rsquo;m not sure the quality of the code improved there. No point for mypy.&lt;/p&gt;
&lt;h2 id=&#34;save_config&#34;&gt;save_config&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#save_config&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Options&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, url, shallow=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.shallow: &lt;span style=&#34;color:#24909d&#34;&gt;bool&lt;/span&gt; = shallow
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.url: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt; = url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;save_config&lt;/span&gt;(options: Options):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    config = &lt;span style=&#34;color:#24909d&#34;&gt;dict&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    config[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;] = options.url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    config[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shallow&amp;#34;&lt;/span&gt;] = options.shallow
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;with&lt;/span&gt; self.cfg_path.open(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;w&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; fp:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ruamel.yaml.dump(config, fp)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We are using &lt;code&gt;save_config&lt;/code&gt; to serialize a &amp;ldquo;value object&amp;rdquo; (the &lt;code&gt;Options&lt;/code&gt; class) into a YAML file.&lt;/p&gt;
&lt;p&gt;mypy saw the first two lines, &lt;code&gt;config = dict()&lt;/code&gt;, &lt;code&gt;config[&amp;quot;url&amp;quot;] = options.ul&lt;/code&gt; and wrongly deduced that &lt;code&gt;config&lt;/code&gt; was a dict from strings to strings.&lt;/p&gt;
&lt;p&gt;Then it complained about &lt;code&gt;config[&amp;quot;shallow&amp;quot;]&lt;/code&gt; that was assigned to a boolean.&lt;/p&gt;
&lt;p&gt;We can fix that by forcing the &lt;code&gt;config&lt;/code&gt; type to be a dict from string to &lt;code&gt;Any&lt;/code&gt;: &lt;code&gt;Any&lt;/code&gt; is a &amp;ldquo;magic&amp;rdquo; type we can use precisely for &lt;a href=&#34;http://mypy.readthedocs.io/en/latest/kinds_of_types.html#the-any-type&#34;&gt;this kind of situation&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- config = dict()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ config: Dict[str, Any] = dict()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This a bit annoying, but the type annotation makes it clearer what the &lt;code&gt;config&lt;/code&gt; is. 1 point for mypy.&lt;/p&gt;
&lt;h2 id=&#34;encoding-project-names&#34;&gt;Encoding project names&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#encoding-project-names&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you use the GitLab API, you often have to use the &amp;lsquo;project id&amp;rsquo;. The doc says you can use the &lt;code&gt;&amp;lt;namespace&amp;gt;/&amp;lt;project_name&amp;gt;&lt;/code&gt; string if it is &amp;ldquo;url encoded&amp;rdquo;, like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Get info about the Foo project in the FooFighters namespace:
GET  /api/v4/projects/FooFighters%2Foo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In python, the naive approach does not work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;urllib.parse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; urllib.parse.quote(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;FooFighters/Foo&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FooFighters/Foo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Instead you have to specify a list of &amp;ldquo;safe&amp;rdquo; characters, that is characters that you &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; need to encode.&lt;/p&gt;
&lt;p&gt;The doc says the default value is &amp;ldquo;/&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Thus, here&amp;rsquo;s what we use in &lt;code&gt;tsrc.gitlab&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;project_id = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt; % (namespace, project)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;encoded_project_id = urllib.parse.quote(project_name, safe=&lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;mypy saw that the default value was a string, so he complained we were using a list instead. We fixed it by:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        encoded_project_name = urllib.parse.quote(project_name, safe=list())
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+        encoded_project_name = urllib.parse.quote(project_name, safe=&amp;#34;&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here, mypy forced us to follow an implicit convention. There are two ways to represent a list of characters in Python. A real list: &lt;code&gt;[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]&lt;/code&gt;, or a string: &lt;code&gt;&amp;quot;abc&amp;quot;&lt;/code&gt;. The authors of the &lt;code&gt;urllib.quote()&lt;/code&gt; function decided to use the second form, so it&amp;rsquo;s a good thing we follow this convention too.&lt;/p&gt;
&lt;p&gt;An other win for mypy.&lt;/p&gt;
&lt;h2 id=&#34;bugs-found&#34;&gt;Bugs found&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#bugs-found&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We already use a lot of tools in the hope of catching bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every pull request was reviewed by other humans&lt;/li&gt;
&lt;li&gt;Two static analyzers (pylint and pyflakes) were ran for  each pull request&lt;/li&gt;
&lt;li&gt;McCabe complexity was measured for each and every function and method of the code base and was not allowed to go above 10.&lt;/li&gt;
&lt;li&gt;TDD was used throughout the development of the project&lt;/li&gt;
&lt;li&gt;Test coverage was already at 80%&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite of this, mypy found bugs that tests, all the linters and all the reviewers did not find.&lt;/p&gt;
&lt;p&gt;Here are a few of them. Feel free to try and find the bug yourself, the answer will be given after the ⁂ symbol.&lt;/p&gt;
&lt;h3 id=&#34;handle_stream_errors&#34;&gt;handle_stream_errors&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#handle_stream_errors&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;GitLabAPIError&lt;/span&gt;(GitLabError):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, url: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, status_code: &lt;span style=&#34;color:#24909d&#34;&gt;int&lt;/span&gt;, message: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;handle_stream_errors&lt;/span&gt;(response: requests.models.Response) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; response.status_code &amp;gt;= &lt;span style=&#34;color:#3677a9&#34;&gt;400&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitLabAPIError(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.url, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Incorrect status code:&amp;#34;&lt;/span&gt;, response.status_code)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code wraps calls to the GitLab API, and arrange for a particular &lt;code&gt;GitLabAPIError&lt;/code&gt; to be raised, when we make a &amp;ldquo;stream&amp;rdquo; request. (For instance, to download a GitLab CI artifact):&lt;/p&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;The problem here is that we inverted the &lt;code&gt;status_code&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt; parameter. Easy to fix:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        raise GitLabAPIError(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-           response.url, &amp;#34;Incorrect status code:&amp;#34;, response.status_code)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+        raise GitLabAPIError(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+           response.url, response.status_code, &amp;#34;Incorrect status code&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The bug was not caught because the code in question was actually copy/pasted from a CI script (and you usually don&amp;rsquo;t write tests for CI scripts).&lt;/p&gt;
&lt;p&gt;We actually don&amp;rsquo;t need streamed responses anywhere in tsrc, so this is in fact dead code (and it is now gone from the code base)&lt;/p&gt;
&lt;h3 id=&#34;handle_json_errors&#34;&gt;handle_json_errors&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#handle_json_errors&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;handle_json_errors&lt;/span&gt;(response: requests.models.Response):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         json_details = response.json()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;except&lt;/span&gt; &lt;span style=&#34;color:#bbb&#34;&gt;ValueError&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     json_details[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;] = (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Expecting json result, got &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt; % response.text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url = response.url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;400&lt;/span&gt; &amp;lt;= status_code &amp;lt; &lt;span style=&#34;color:#3677a9&#34;&gt;500&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; key &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; key &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; json_details:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitLabAPIError(url, status_code, json_details[key])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitLabAPIError(url, status_code, json_details)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; status_code &amp;gt;= &lt;span style=&#34;color:#3677a9&#34;&gt;500&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitLabAPIError(url, status_code, response.text)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This one is slightly more interesting. It is located near the previous one and handles errors for the calls to the GitLab API which returns JSON objects.&lt;/p&gt;
&lt;p&gt;We of course have to catch 500 errors, which hopefully do not happen often.&lt;/p&gt;
&lt;p&gt;In case of a status code between 400 and 499, we know there was a problem in the request we made, but we need to tell the user why the request was rejected.&lt;/p&gt;
&lt;p&gt;Most of the time the GitLab API returns a JSON object containing a &lt;code&gt;error&lt;/code&gt; or &lt;code&gt;message&lt;/code&gt; key, but sometimes neither key is found in the returned object, and sometimes the text of the response is not even valid JSON code.&lt;/p&gt;
&lt;p&gt;So we have to check for both keys in the JSON object, and if not found (if we exit the for loop), just store the entire JSON response in the exception.&lt;/p&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;The bug is in the second &lt;code&gt;raise GitLabAPIError&lt;/code&gt;. We are passing an entire object where the &lt;code&gt;GitLabAPIError&lt;/code&gt; expected a string.&lt;/p&gt;
&lt;p&gt;The fix was:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- raise GitLabAPIError(url, status_code, json_details)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ raise GitLabAPIError(url, status_code, json.dumps(json_details, indent=2))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, this was hard to catch with tests. The case where the JSON returned by GitLab did &lt;em&gt;not&lt;/em&gt; contain a &lt;code&gt;error&lt;/code&gt; or &lt;code&gt;message&lt;/code&gt; key only happened once in the lifetime of the project (which explain why the code was written), so manual QA and unit tests did not need to check this code path.&lt;/p&gt;
&lt;p&gt;Anyway, note we did not blindly wrote something like &lt;code&gt;str(json_details)&lt;/code&gt; to convert the JSON object to a string. We found out it was used in a message displayed to the end user, thus we use &lt;code&gt;json.dumps(json_details), indent=2)&lt;/code&gt; to make sure the message contains neatly indented JSON and is easy to read.&lt;/p&gt;
&lt;h4 id=&#34;localmanifest&#34;&gt;LocalManifest&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#localmanifest&#34;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;LocalManifest&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, workspace_path: Path) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        hidden_path = workspace_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;.tsrc&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.clone_path = hidden_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;manifest&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.cfg_path = hidden_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;manifest.yml&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.manifest: Optional[tsrc.manifest.Manifest] = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;update&lt;/span&gt;(self) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ui.info_2(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Updating manifest&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tsrc.git.run_git(self.clone_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;fetch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tsrc.git.run_git(self.clone_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;reset&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--hard&amp;#34;&lt;/span&gt;, branch)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;load&lt;/span&gt;(self) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        yml_path = self.clone_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;manifest.yml&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; yml_path.exists():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            message = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;No manifest found in &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;. Did you run `tsrc init` ?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; tsrc.Error(message.format(yml_path))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.manifest = tsrc.manifest.load(yml_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;copyfiles&lt;/span&gt;(self) -&amp;gt; List[Tuple[&lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;]]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self.manifest.copyfiles
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_repos&lt;/span&gt;(self) -&amp;gt; List[tsrc.Repo]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; self.manifest, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;manifest is empty. Did you call load()?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self.manifest.get_repos(groups=self.active_groups)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After you run &lt;code&gt;tsrc init git@example.com/manifest.git&lt;/code&gt;, the manifest is cloned inside &lt;code&gt;&amp;lt;workspace&amp;gt;/.tsrc/manifest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Thus, the contents of the &lt;code&gt;manifest.yml&lt;/code&gt; is in &lt;code&gt;&amp;lt;workspace&amp;gt;/.tsrc/manifest/manifest.yml&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;LocalManifest&lt;/code&gt; class represent this manifest repository.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what happens when you run &lt;code&gt;tsrc sync&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;local_manifest.update()&lt;/code&gt; is called: the repository in &lt;code&gt;&amp;lt;workspace&amp;gt;/.tsrc/manifest&amp;gt;&lt;/code&gt; is updated by running &lt;code&gt;git fetch; git reset --hard origin/master&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;local_manifest.load()&lt;/code&gt; is called: the &lt;code&gt;manifest.yml&lt;/code&gt; file is parsed, and its contents are stored in the &lt;code&gt;self.manifest&lt;/code&gt; attribute.&lt;/li&gt;
&lt;li&gt;Then the &lt;code&gt;Syncer&lt;/code&gt; class calls &lt;code&gt;local_manifest.get_repos()&lt;/code&gt; to find out the list of repositories to clone or synchronise.&lt;/li&gt;
&lt;li&gt;Finally, the &lt;code&gt;FileCopier&lt;/code&gt; class uses &lt;code&gt;local_manifest.copyfiles&lt;/code&gt; to perform file copies.&lt;/li&gt;
&lt;/ul&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;It&amp;rsquo;s not really a bug, but mypy forced us to acknowledge that &lt;code&gt;LocalManifest.manifest&lt;/code&gt; starts as None, and only gets its real value after &lt;code&gt;.load()&lt;/code&gt; has been called.&lt;/p&gt;
&lt;p&gt;We already have an &lt;code&gt;assert&lt;/code&gt; in place in &lt;code&gt;get_repos()&lt;/code&gt;, but mypy forced us to add a similar check in the &lt;code&gt;copyfiles&lt;/code&gt; getter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @property
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    def copyfiles(self) -&amp;gt; List[Tuple[str, str]]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+       assert self.manifest, &amp;#34;manifest is empty. Did you call load()?&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;        return self.manifest.copyfiles
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;gitserver&#34;&gt;GitServer&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#gitserver&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some of the tests for tsrc are what we call end-to-end tests:&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how they work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We create a band new temporary directory for each test&lt;/li&gt;
&lt;li&gt;In it, we create a &lt;code&gt;srv&lt;/code&gt; directory with bare git repositories&lt;/li&gt;
&lt;li&gt;Then, we create a &lt;code&gt;work&lt;/code&gt; directory and we run tsrc commands from there.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thus, we don&amp;rsquo;t have to mock file systems or git commands (which is doable but pretty hard), and things are easy to debug because in case of problem we can just &lt;code&gt;cd&lt;/code&gt; to the test directory and inspect the state of the git repositories by hand.&lt;/p&gt;
&lt;p&gt;Any way, those tests are written with a test helper called &lt;code&gt;GitServer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can use this class to create git repositories, push files on some branches, and so on:&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the helper looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;add_repo&lt;/span&gt;(self, name: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, default_branch=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;master&amp;#34;&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        url = self.get_url(name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;push_file&lt;/span&gt;(self, name: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, file_path: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, *,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  contents=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, message=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        full_path = ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        full_path.parent.makedirs_p()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        full_path.touch()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; contents:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            full_path.write_text(contents)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        commit_message = message &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;or&lt;/span&gt; (&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Create/Update &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt; % file_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_git(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;add&amp;#34;&lt;/span&gt;, file_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_git(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;commit&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--message&amp;#34;&lt;/span&gt;, commit_message)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_git(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;push&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;origin&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--set-upstream&amp;#34;&lt;/span&gt;, branch)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;tag&lt;/span&gt;(self, name: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, tag_name: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_git(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;tag&amp;#34;&lt;/span&gt;, tag_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_git(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;push&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;origin&amp;#34;&lt;/span&gt;, tag_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_tags&lt;/span&gt;(self, name: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;) -&amp;gt; List[&lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         src_path = self.get_path(name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         rc, out = tsrc.git.run_git_captured(src_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;tag&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--list&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can use it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_tsrc_sync&lt;/span&gt;(tsrc_cli: CLI, git_server: GitServer) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_server.add_repo(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;foo/bar&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_server.add_repo(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;spam/eggs&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    manifest_url = git_server.manifest_url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tsrc_cli.run(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;init&amp;#34;&lt;/span&gt;, manifest_url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_server.push_file(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;foo/bar&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bar.txt&amp;#34;&lt;/span&gt;, contents=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;this is bar&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tsrc_cli.run(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bar_txt_path = workspace_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bar.txt&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; bar_txt_path.text() == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;this is bar&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;The bug is in &lt;code&gt;get_tags&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    def get_tags(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         rc, out = tsrc.git.run_git(src_path, &amp;#34;tag&amp;#34;, raises=False)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        return out
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+        return out.splitlines()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;get_tags&lt;/code&gt; methods is also dead code. It has an interesting story.&lt;/p&gt;
&lt;p&gt;The need for the &lt;code&gt;GitServer&lt;/code&gt; helper occurred when I started writing end-to-end tests for tsrc and discovered I needed a test framework to write those end-to-end test.&lt;/p&gt;
&lt;p&gt;It was vital that the &lt;code&gt;GitServer&lt;/code&gt; implementation uses clean code.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One, we must be sure &lt;code&gt;GitServer&lt;/code&gt; has no bugs. Otherwise, we may get stuck looking for bugs in our production code when tests fail.&lt;/li&gt;
&lt;li&gt;For the same reason, &lt;code&gt;GitServer&lt;/code&gt; should be easy to change. There will almost certainly be features added in tsrc that will require adapting &lt;code&gt;GitServer&lt;/code&gt; code in order to properly test it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So to have a clean implementation of the &lt;code&gt;GitServer&lt;/code&gt; I of course used the best technique I know of: TDD.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://dmerej.info/blog/pics/yo-dawg-test.jpg&#34; alt=&#34;yo dawg tests&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can find them in the [test_git_server.py](&lt;a href=&#34;https://github.com/dmerejkowsky/tsrc/blob/main/tsrc/test/helpers/test_git_server.py&#34;&gt;https://github.com/dmerejkowsky/tsrc/blob/main/tsrc/test/helpers/test_git_server.py&lt;/a&gt; file.&lt;/p&gt;
&lt;p&gt;Anyway, I was writing an end-to-end test for tsrc that involved tags.&lt;/p&gt;
&lt;p&gt;I thought: &amp;ldquo;OK, I need a &lt;code&gt;.tag()&lt;/code&gt; method in &lt;code&gt;GitServer&lt;/code&gt;. So I also need a &lt;code&gt;get_tags()&lt;/code&gt; method to check the tag was actually pushed&amp;rdquo;.   Thus I wrote the &lt;code&gt;get_tags&lt;/code&gt; method, forgetting to write a failing test for &lt;code&gt;GitServer&lt;/code&gt; first (that still happens after 5 years of TDD, so don&amp;rsquo;t worry if it happens to you too.). At that point I only had my end-to-end test failing, so I made it pass and completely forgot about the &lt;code&gt;get_tags()&lt;/code&gt; method. Oh well.&lt;/p&gt;
&lt;h3 id=&#34;executors-and-tasks&#34;&gt;Executors and Tasks&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#executors-and-tasks&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the implementation of tsrc we often have to loop over a list of items, perform actions an each of them and record which one failed, and when the loop is done, display the error messages to the user.&lt;/p&gt;
&lt;p&gt;For instance:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tsrc sync
* (1/2) foo/bar
remote: Counting objects: 3, done.
...
Updating 62a5d28..39eb3bd
error: The following untracked files would be overwritten by merge:
	bar.txt
Please move or remove them before you merge.
Aborting
* (2/2) spam/eggs
Already up to date.
Error: Synchronize workspace failed
* foo/bar: updating branch failed
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$tsrc foreach
:: Running `ls foo` on every repo
* (1/2) foo
$ ls foo
bar.txt
* (2/2) spam
$ ls foo
ls: cannot access &amp;#39;foo&amp;#39;: No such file or directory
Error: Running `ls foo` on every repo failed
* spam
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So in order to keep things &lt;abbr title=&#34;Don&#39;t Repeat Yourself&#34;&gt;DRY&lt;/abbr&gt;, we have some high-level code that only deals with loop and error handling:&lt;/p&gt;
&lt;p&gt;First, a generic &lt;code&gt;Task&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;(Note that you can have your &lt;a href=&#34;https://mypy.readthedocs.io/en/latest/generics.html&#34;&gt;own generic types&lt;/a&gt; with mypy. This is &lt;em&gt;awesome&lt;/em&gt; because without it you get laughed at by C++ programmers)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Task&lt;/span&gt;(Generic[T], metaclass=abc.ABCMeta):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@abc.abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;description&lt;/span&gt;(self) -&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@abc.abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;display_item&lt;/span&gt;(self, item: T) -&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@abc.abstractmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;process&lt;/span&gt;(self, item: T) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then, a generic &lt;code&gt;SequentialExecutor&lt;/code&gt; who knows how to execute a given task on a list of items and display the outcome:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;SequentialExecutor&lt;/span&gt;(Generic[T]):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, task: Task[T]) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.task = task
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.errors: List[Tuple[Any, tsrc.Error]] = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;process&lt;/span&gt;(self, items: List[T]) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ui.info_1(self.task.description())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.errors = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;enumerate&lt;/span&gt;(items):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.process_one(item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.errors:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.handle_errors()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;process_one&lt;/span&gt;(self, item: T) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.task.process(item)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;except&lt;/span&gt; tsrc.Error &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; error:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.errors.append((item, error))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;handle_errors&lt;/span&gt;(self) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Display nice error message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; ExecutorFailed()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Thus we can inherit from &lt;code&gt;Task&lt;/code&gt; to implement &lt;code&gt;tsrc sync&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Syncer&lt;/span&gt;(tsrc.executor.Task[Repo]):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;process&lt;/span&gt;(self, repo: Repo) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ui.info(repo.src)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.fetch(repo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.check_branch(repo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.sync_repo_to_branch(repo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;check_branch&lt;/span&gt;(self, repo: Repo):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        current_branch = tsrc.git.get_current_branch(repo_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; current_branch:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; tsrc.Error(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Not on any branch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ditto for &lt;code&gt;tsrc foreach&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;CmdRunner&lt;/span&gt;(tsrc.executor.Task[Repo]):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;process&lt;/span&gt;(self, repo: Repo) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        full_path = self.workspace.joinpath(repo.src)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rc = subprocess.call(cmd, ...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; rc != &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; CommandFailed
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Did you spot the bug?&lt;/p&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;The bug is in here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;process&lt;/span&gt;(self, items: List[T]) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; items:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the result of a bad refactoring. &lt;code&gt;Executor&lt;/code&gt; used to track success of task by looking at the return value the &lt;code&gt;process()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;After a while, I found out it was clearer to just use exceptions for that, mostly when I implemented the &lt;code&gt;Syncer&lt;/code&gt; class. (You can just raise an exception instead of adding lots of &lt;code&gt;ifs&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;But the early &lt;code&gt;return True&lt;/code&gt; was left. Here &lt;code&gt;mypy&lt;/code&gt; found something that would have puzzled an external reader. Almost everything function or method dealing with Executors and Tasks in tsrc either return None or raise Exception. What is that boolean doing here?&lt;/p&gt;
&lt;p&gt;There were of course no tests left that checked the return value of &lt;code&gt;process&lt;/code&gt; (they got refactored at the same time of the rest of the code), so the bug went unnoticed.&lt;/p&gt;
&lt;h3 id=&#34;run_git&#34;&gt;run_git&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#run_git&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The last changed required by mypy was also pretty interesting. Here&amp;rsquo;s the deal.&lt;/p&gt;
&lt;p&gt;In tsrc, we often need to run &lt;code&gt;git&lt;/code&gt; commands, but we can run them in two very different ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can either just run the command and let its output directly being displayed to the user. This is useful for things like &lt;code&gt;git fetch&lt;/code&gt; which can take some times and for which the output contains an indication of progress for the user.&lt;/li&gt;
&lt;li&gt;Or we just need to run the command, capture its output and deal with it as a value. For instance, if we want to get the url of the &amp;ldquo;origin&amp;rdquo; remote, we can call &lt;code&gt;git remote get-url origin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In both cases, we must handle the possibility that the command can fail.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s what the implementation looked like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;run_git&lt;/span&gt;(working_path, *cmd, raises=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34; Run git `cmd` in given `working_path`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    If `raises` is True and git return code is non zero, raise
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    an exception. Otherwise, return a tuple (returncode, out)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_cmd = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;(cmd)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_cmd.insert(&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;git&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options = &lt;span style=&#34;color:#24909d&#34;&gt;dict&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; raises:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;] = subprocess.PIPE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;stderr&amp;#34;&lt;/span&gt;] = subprocess.STDOUT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    process = subprocess.Popen(git_cmd, cwd=working_path, **options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; raises:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        process.wait()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        out, _ = process.communicate()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        out = out.decode(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;utf-8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    returncode = process.returncode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; raises:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; returncode != &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitCommandError(working_path, cmd)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; returncode, out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here&amp;rsquo;s how to use it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# run `git fetch`, leaving the output as-is&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;run_git(foo_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;fetch&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# run git remote get-url origin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rc, out = run_git(foo_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;remote&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;get-url&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;origin&amp;#34;&lt;/span&gt;, raises=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; rc == &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Handle the case where there is no remote called &amp;#39;origin&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Do something with out&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s an other place we used &lt;code&gt;run_git&lt;/code&gt;: we have a command named &lt;code&gt;tsrc status&lt;/code&gt;, which displays a summary of the whole workspace. Here what&amp;rsquo;s its output looks like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;tsrc status
* foo master ↓1 commit
* bar devel ↑1 commit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And here is the implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;GitStatus&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;update_remote_status&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _, ahead_rev = run_git(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.working_path,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;rev-list&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;@&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{upstream}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;..HEAD&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            raises=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.ahead = &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(ahead_rev.splitlines())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _, behind_rev = run_git(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.working_path,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;rev-list&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;HEAD..@&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{upstream}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            raises=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.behind = &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(behind_rev.splitlines())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Found the bug yet?&lt;/p&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;The code in &lt;code&gt;update_remote_status()&lt;/code&gt; assumes that &lt;code&gt;git rev-list&lt;/code&gt; outputs a list of commits, and then count the lines in the output.&lt;/p&gt;
&lt;p&gt;This works well if there &lt;em&gt;is&lt;/em&gt; a remote branch configured:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git revlist HEAD..@{upstream}
30f729a6a0ec3926cf063f5f8a3953b89d7b252e
ef564f0ef38a163beb3db52474ac4e256a6c2cd4
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But if not remote is configured, the git command will fail with a message looking like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ git revlist HEAD..@{upstream}
fatal: no upstream configured for branch &amp;#39;dm/foo&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since &lt;code&gt;update_remote_status()&lt;/code&gt; does not check the return code, &lt;code&gt;self.ahead_rev&lt;/code&gt; and &lt;code&gt;self.behind_rev&lt;/code&gt; both get set to &lt;code&gt;1&lt;/code&gt;, and the output looks like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* foo other-branch ↑1↓1 commit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oops.&lt;/p&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;But there is more to it than just this bug.&lt;/p&gt;
&lt;p&gt;Notice the type of the return value of &lt;code&gt;run_git&lt;/code&gt; depends &lt;em&gt;on the value of the &lt;code&gt;raises&lt;/code&gt; parameter&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;At first I tried to annotate the function with a &lt;code&gt;Union&lt;/code&gt; type, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;run_git&lt;/span&gt;(working_path: Path, *cmd: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, raises=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;) -&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Union[Tuple[&lt;span style=&#34;color:#24909d&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;], &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But then mypy complained for each and every line that used &lt;code&gt;run_git&lt;/code&gt; with &lt;code&gt;raises=False&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;rc, out = run_git(..., raises=False)

foo.py:39: error: &amp;#39;builtins.None&amp;#39; object is not iterable
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I thought about this and found out it was cleaner to split &lt;code&gt;run_git&lt;/code&gt; into &lt;code&gt;run_git&lt;/code&gt; and &lt;code&gt;run_git_captured&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;run_git&lt;/span&gt;(working_path: Path, *cmd: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34; Run git `cmd` in given `working_path`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    Raise GitCommandError if return code is non-zero.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_cmd = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;(cmd)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_cmd.insert(&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;git&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    returncode = subprocess.call(git_cmd, cwd=working_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; returncode != &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitCommandError(working_path, cmd)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;run_git_captured&lt;/span&gt;(working_path: Path, *cmd: &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                     check: &lt;span style=&#34;color:#24909d&#34;&gt;bool&lt;/span&gt; = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;) -&amp;gt; Tuple[&lt;span style=&#34;color:#24909d&#34;&gt;int&lt;/span&gt;, &lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34; Run git `cmd` in given `working_path`, capturing the output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    Return a tuple (returncode, output).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    Raise GitCommandError if return code is non-zero and check is True
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_cmd = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;(cmd)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    git_cmd.insert(&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;git&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options: Dict[&lt;span style=&#34;color:#24909d&#34;&gt;str&lt;/span&gt;, Any] = &lt;span style=&#34;color:#24909d&#34;&gt;dict&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;stdout&amp;#34;&lt;/span&gt;] = subprocess.PIPE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;stderr&amp;#34;&lt;/span&gt;] = subprocess.STDOUT
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    returncode = process.returncode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; check &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;and&lt;/span&gt; returncode != &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;raise&lt;/span&gt; GitCommandError(working_path, cmd, output=out)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; returncode, out
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;True, there&amp;rsquo;s a bit more code and slightly duplication but:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The multiple &lt;code&gt;if raises&lt;/code&gt; in the original implementation are gone. Less &lt;code&gt;if&lt;/code&gt; in a function is always a win.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;raises&lt;/code&gt; parameter did too very different things:
&lt;ul&gt;
&lt;li&gt;One, it changed the return type of the function&lt;/li&gt;
&lt;li&gt;Two, it forced the caller to explicitly handle the case where the command fails.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now the intent about whether you want to capture the output or not is encoded &lt;em&gt;in the name of the function&lt;/em&gt; (&lt;code&gt;run_git_captured&lt;/code&gt; instead of &lt;code&gt;run_git&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Also note that you can&amp;rsquo;t forget about checking the return code anymore.&lt;/p&gt;
&lt;p&gt;You can either write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;_, out = run_git_captured(repo_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;some-cmd&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# We know `out` is *not* an error message, because if `some-cmd` failed, an&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# exception would have been raised before `out` was set.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or you can be explicit about your error handling:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rc, out = run_git_captured(repo_path, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;some-cmd&amp;#34;&lt;/span&gt;, check=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; rc == &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Ditto, out can&amp;#39;t be an error message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Need to handle error here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That alone would be a good reason to use mypy I think :)&lt;/p&gt;
&lt;h1 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#whats-next&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Well, the &lt;code&gt;mypy&lt;/code&gt; changes have &lt;a href=&#34;https://github.com/dmerejkowsky/tsrc/pull/110&#34;&gt;been merged&lt;/a&gt; and the CI now runs &lt;code&gt;mypy&lt;/code&gt; in strict mode on every pull request.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m still curious about the other benefits of type annotations I could not check (maintainability, code comprehension, ease of refactorings &amp;hellip;).&lt;/p&gt;
&lt;p&gt;I guess we&amp;rsquo;ll see how the next refactoring in tsrc goes.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update, a few months later&lt;/em&gt;: Well, the next refactoring in tsrc went really well and mypy caught a ton of problems very early. I&amp;rsquo;m now using &lt;code&gt;mypy&lt;/code&gt; in strict mode in almost all of my projects.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We saw how mypy, while stilling making relative few false positives, still found inconsistencies, a few bugs, and even design problems.&lt;/p&gt;
&lt;p&gt;So, my advice is for you to use it if you get a chance. Cheers!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;If you want to know more, feel free to browse the &lt;a href=&#34;https://dmerejkowsky.github.io/tsrc/&#34;&gt;documentation&lt;/a&gt;, or read the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-tsrc/&#34;&gt;introduction post&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 6: Cross-compilation for Android</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-6-android-cross-compilation/</link>
      <pubDate>Tue, 05 Jun 2018 10:17:17 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-6-android-cross-compilation/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 6 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;After our little detour talking about how to wrap C++ in Python, we now are ready to tackle writing Android applications using C++ code.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll start with a simple challenge: try and run a simple &amp;ldquo;Hello, world&amp;rdquo; program written in C inside a simulator and on our phone.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get started!&lt;/p&gt;
&lt;h2 id=&#34;a-naive-try&#34;&gt;A naive try&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-naive-try&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s see what happens if we naively try to run some C code on our phone.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, let&amp;rsquo;s install the Android SDK so that we can use the &lt;code&gt;adb&lt;/code&gt; tool.&lt;/li&gt;
&lt;li&gt;Then, let&amp;rsquo;s activate the developer mode on the phone, and plug it to our laptop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&amp;rsquo;s compile a simple C program:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;/* in hello.c */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Hello, world&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ gcc hello.c -o hello
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, let&amp;rsquo;s use &lt;code&gt;adb push&lt;/code&gt; to copy the binary on our phone, and &lt;code&gt;adb shell&lt;/code&gt; to try and run it:&lt;/p&gt;
&lt;p&gt;(Note that &lt;code&gt;/data/local/tmp&lt;/code&gt; is the only directory I found where we can run executables):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ adb push hello /data/local/tmp
$ adb shell
$ cd /data/local/tmp
$ ./hello
/system/bin/sh: ./hello: not executable: 64-bit ELF file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hum. What just happened ?&lt;/p&gt;
&lt;h2 id=&#34;cpu-architectures&#34;&gt;CPU architectures&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#cpu-architectures&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When you use a compiler, you get a binary file from the source code. You can think of this binary file as a list of instructions, ready to be used by a CPU.&lt;/p&gt;
&lt;p&gt;The trick is that different CPU have different &lt;em&gt;instructions sets&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For instance, it is very likely that the CPU you have on your laptop is a &lt;code&gt;x86_64&lt;/code&gt; CPU, and that the CPU of you phone is an &lt;code&gt;armv7&lt;/code&gt;. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This means that a binary you built for a &lt;code&gt;x86_64&lt;/code&gt; CPU will not run on a &lt;code&gt;armv7&lt;/code&gt; CPU.&lt;/p&gt;
&lt;h2 id=&#34;the-libc&#34;&gt;The libc&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-libc&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;OK, but the Android SDK also comes with a simulator, and we can choose the CPU architecture.&lt;/p&gt;
&lt;p&gt;Can&amp;rsquo;t we just use a &lt;code&gt;x86_64&lt;/code&gt; Android simulator ?&lt;/p&gt;
&lt;p&gt;If we try the same thing with a &lt;code&gt;x86_64&lt;/code&gt; simulator, we get an even weirder error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ adb push hello /data/local/tmp
$ adb shell
$ cd /data/local/tmp
$ ./hello
/system/bin/sh: ./hello: no such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The file does exist, but Android does not know how to run it. Why?&lt;/p&gt;
&lt;p&gt;Remember when we used &lt;code&gt;LD_TRACE_LOADED_OBJECTS&lt;/code&gt; back in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/#using-the-chucknorris-shared-library&#34;&gt;a previous post&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Well, if we re-run the binary we just built we can see it loads a few &lt;code&gt;.so&lt;/code&gt; files:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ export LD_TRACE_LOADED_OBJECTS=1
$ ./hello

  linux-vdso.so.1 (0x00007ffc1ad96000)
  libc.so.6 =&amp;gt; /usr/lib/libc.so.6 (0x00007fb017147000)
  /lib64/ld-linux-x86-64.so.2 (0x00007fb017503000)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Those files do not exist on Android, because even if Android is based on Linux, it&amp;rsquo;s still a different operating system.&lt;/p&gt;
&lt;p&gt;See the line about &lt;code&gt;libc.so.6&lt;/code&gt; ? That&amp;rsquo;s the library that contains the code for the &lt;code&gt;printf&lt;/code&gt; function we just used.&lt;/p&gt;
&lt;p&gt;We call such a library &amp;ldquo;the libc&amp;rdquo;, which is a bit misleading.&lt;/p&gt;
&lt;p&gt;There are several &lt;em&gt;implementations&lt;/em&gt; of &amp;ldquo;the libc&amp;rdquo;. On your laptop you are probably using &lt;code&gt;glibc&lt;/code&gt;. There are other implementations like &lt;code&gt;musl&lt;/code&gt; for instance. Android uses yet an other implementation called &lt;code&gt;bionic&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So if want to achieve our goal (running the &amp;ldquo;Hello, world&amp;rdquo; C program on a simulator and on a phone), we have to do two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure we can tell the compiler about the CPU architecture&lt;/li&gt;
&lt;li&gt;Make sure we use the correct libc&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is tricky because by default, compilers use the  same CPU architecture and the same libc used by the operating system they run on&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;This is what we call &amp;ldquo;cross-compilation&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;using-the-ndk-to-compile-by-hand&#34;&gt;Using the NDK to compile by hand&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-the-ndk-to-compile-by-hand&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Google provides a set of tools know as the &lt;em&gt;NDK&lt;/em&gt; in order to help us cross-compiling code for Android.&lt;/p&gt;
&lt;p&gt;Here we are using version &lt;code&gt;r16&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we download and extract the NDK, here&amp;rsquo;s how we can compile and link our &amp;ldquo;Hello, World&amp;rdquo; program:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;export NDK_ROOT=/path/to/ndk

${NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
  --target=x86_64-none-linux-android
  --gcc-toolchain=${NDK_ROOT}/toolchains/x86_64-4.9/prebuilt/linux-x86_64
  --sysroot=${NDK_ROOT}/sysroot
  -isystem ${NDK_ROOT}/sysroot/usr/include/x86_64-linux-android
  -o  hello.c.o -c hello.c

${NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
  --target=x86_64-none-linux-android
  --gcc-toolchain=${NDK_ROOT}/toolchains/x86_64-4.9/prebuilt/linux-x86_64
  --sysroot  ${NDK_ROOT}/platforms/android-21/arch-x86_64
  -pie hello.c.o -o hello
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Some notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We have to specify the Android API level (21 here) like in any other project targeting Android&lt;/li&gt;
&lt;li&gt;Most of the magic is done by the &lt;code&gt;--sysroot&lt;/code&gt;, &lt;code&gt;--gcc-toolchain&lt;/code&gt; and &lt;code&gt;--target&lt;/code&gt; options.&lt;/li&gt;
&lt;li&gt;We have to specify &lt;code&gt;-fPIE&lt;/code&gt;, a flag that means &lt;em&gt;position independant executable&lt;/em&gt;. It serves the same kind of purpose as the &lt;code&gt;-fPIC&lt;/code&gt; flag we met in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/#building-the-shared-library&#34;&gt;a previous article&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And now we can upload and run the binary on the &lt;code&gt;x86_64&lt;/code&gt; simulator:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ adb push hello /data/local/tmp
$ adb shell /data/local/tmp/hello
Hello, world
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can do the same thing for &lt;code&gt;arm&lt;/code&gt; of course, but note how subtle the changes are to go from &lt;code&gt;x86_64&lt;/code&gt; to &lt;code&gt;arm&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;export NDK_ROOT=/home/dmerej/Android/Sdk/ndk-bundle

${NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
  --target=armv7-none-linux-androideabi
  --gcc-toolchain=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.9/...
  --sysroot=${NDK_ROOT}/sysroot
  -isystem ${NDK_ROOT}/sysroot/usr/include/arm-linux-androideabi
  -o  hello.c.o -c hello.c

${NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
  --target=armv7-none-linux-androideabi
  --gcc-toolchain=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.9/...
  --sysroot  ${NDK_ROOT}/platforms/android-21/arch-arm
  -pie hello.c.o -o hello
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And if we try again:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ adb push hello /data/local/tmp
$ adb shell /data/local/tmp/hello
Hello, world
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;p&gt;Our next objective is to run the &lt;code&gt;cpp_demo&lt;/code&gt; executable we used to test the Chuck Norris library in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-1-cmake-ninja/#the-test-program&#34;&gt;part 1&lt;/a&gt; on our phone and on the Android simulator.&lt;/p&gt;
&lt;p&gt;Things is going to be trickier because of the &lt;code&gt;sqlite3&lt;/code&gt; dependency and the fact that the code is written in C++.&lt;/p&gt;
&lt;p&gt;But surely there is a better way to than guessing how to invoke the compilers and linkers.&lt;/p&gt;
&lt;h1 id=&#34;conan-to-the-rescue&#34;&gt;Conan to the rescue&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conan-to-the-rescue&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Of course, we could have used the native plug-in of Android Studio directly.&lt;/p&gt;
&lt;p&gt;Instead we will use Conan, the tool we talked about in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-2-sqlite-conan/&#34;&gt;part 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using Conan is a good way to abstract the above complexity, without loosing any of the control (like depending on an IDE plug-in does).&lt;/p&gt;
&lt;p&gt;Plus, we can apply what we learn using Conan in other contexts such as writing C++ code on iOS.&lt;/p&gt;
&lt;h2 id=&#34;the-standalone-toolchain&#34;&gt;The standalone toolchain&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-standalone-toolchain&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you a look at the contents of the Android NDK, you&amp;rsquo;ll soon realize there are lots of stuff there.&lt;/p&gt;
&lt;p&gt;Among the cross-compiler binaries, sysroot, include directories we used in the previous section we also have a full build system based on Makefiles called &lt;code&gt;ndk-build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The NDK also contains support files for every Android API from 14 to 27 and every processor architecture (aarch64, arm, mips, x86, x86_64).&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s a &lt;em&gt;lot&lt;/em&gt; of stuff and it takes about 3G of disk space.&lt;/p&gt;
&lt;p&gt;However, in &lt;code&gt;build/tools&lt;/code&gt; there&amp;rsquo;s a bash script called &lt;code&gt;make-standalone-toolchain.sh&lt;/code&gt;. Let&amp;rsquo;s take a look:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Creates a toolchain installation for a given Android target.&lt;/p&gt;
&lt;p&gt;The output of this tool is a more typical cross-compiling toolchain. It is
intended to be used with existing build systems such as autotools.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ah-ah! Sound like what we need, especially if later on we start depending on a library built with autotools from the ChuckNorris project.&lt;/p&gt;
&lt;h2 id=&#34;build-requirements&#34;&gt;Build requirements&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#build-requirements&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s now time to introduce a new Conan feature, the build requirements.&lt;/p&gt;
&lt;p&gt;Basically build requirements are packages you only need when building something from sources. See the &lt;a href=&#34;https://docs.conan.io/en/latest/devtools/build_requires.html&#34;&gt;Conan docs&lt;/a&gt; for more information.&lt;/p&gt;
&lt;p&gt;So, here&amp;rsquo;s the plan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First let&amp;rsquo;s have a recipe to download and extract the NDK (hopefully just once)&lt;/li&gt;
&lt;li&gt;Then let&amp;rsquo;s have a second recipe to run the &lt;code&gt;make_standalone_toolchain&lt;/code&gt; script and set up what we need to cross-compile for Android with CMake.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note before we begin: I&amp;rsquo;ll only show you a small fraction of the recipes code. This is for educational purposes: there are a lots of details I have to omit in order to keep things readable.&lt;/p&gt;
&lt;h2 id=&#34;the-ndk-recipe&#34;&gt;The NDK recipe&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-ndk-recipe&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is a simplistic recipe for the NDK:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;AndroidndkConan&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;android-ndk&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;r16&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    settings = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;os_build&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;arch_build&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;source&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        url = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://...android-ndk-&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;-linux-x86_64.zip&amp;#34;&lt;/span&gt; % self.version
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools.download(url, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ndk.zip&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools.unzip(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ndk.zip&amp;#34;&lt;/span&gt;, keep_permissions=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools.unlink(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ndk.zip&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package_info&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools_path = os.path.join(self.package_folder, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;tools&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        env_info = self.env_info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        env_info.PATH.append(os.path.join(tools_path)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;source()&lt;/code&gt; method does nothing but fetching and extracting the NDK.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;package_info()&lt;/code&gt; is more interesting: it adds the &lt;code&gt;build/tools&lt;/code&gt; directory in the &lt;code&gt;env_info.PATH&lt;/code&gt; variable. Any recipe that has the NDK package as build requirement can thus call &lt;code&gt;self.run()&lt;/code&gt; to run any binary from the tools directory, since &lt;code&gt;PATH&lt;/code&gt; will be set accordingly.&lt;/p&gt;
&lt;h2 id=&#34;the-android-toolchain-recipe&#34;&gt;The Android toolchain recipe&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-android-toolchain-recipe&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We can now move on to the next recipe, the Android toolchain:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;AndroidtoolchainConan&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;android-toolchain&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lib_version = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;r16&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    package_version = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;r4&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt; % (lib_version, package_version)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    license = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;GPL/APACHE2&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://github.com/lasote/conan-android-toolchain&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    settings = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiler&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    build_requires = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;android-ndk/r16@dmerej/test&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;build&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      toolchain = get_toolchain_str(self.settings.arch)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      command = (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;make-standalone-toolchain.sh&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--verbose&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--toolchan=&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--platform=android-&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ) % (toolchain, self.settings.os.api_level)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.run(command)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package_info&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sysroot = os.path.join(self.package_folder, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;sysroot&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.env_info.CC =  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.env_info.AR = ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.env_info.CFLAGS = ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, we are able to run the &lt;code&gt;make-standalone-toolchain.sh&lt;/code&gt; script directly with &lt;code&gt;self.run()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The other important part is the &lt;code&gt;package_info()&lt;/code&gt; method, which :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set the sysroot&lt;/li&gt;
&lt;li&gt;Tells the consumers of the package about the path to the binaries used during compilation and linking (CC and AR)&lt;/li&gt;
&lt;li&gt;Set some compile flags via the &lt;code&gt;CFLAGS&lt;/code&gt; variable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember when we built our C binary by hand?&lt;/p&gt;
&lt;p&gt;We can find traces of this data in the command line we used:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;${NDK_ROOT}/.../bin/clang                  &amp;lt;- this is CC
  --sysroot  ${NDK_ROOT}/...               &amp;lt;- this is the sysroot
  --target=armv7-none-linux-androideabi \
  --gcc-toolchain=..                     | &amp;lt;- those are compile flags
  -pie                                  /
  hello.c.o
  -o hello
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that the recipe depends on the architecture we want our compiled code to run on. This means we are going to build one &lt;code&gt;android-toolchain&lt;/code&gt; package per CPU architecture. Also note that the NDK recipe has a setting to know about the Android API level.&lt;/p&gt;
&lt;p&gt;Where can we specify all these configuration values?&lt;/p&gt;
&lt;h2 id=&#34;android-profiles&#34;&gt;Android Profiles&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#android-profiles&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s an elegant way to solve this.&lt;/p&gt;
&lt;p&gt;We create a global Conan profile in &lt;code&gt;~/.conan/profiles/android&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[build_requires]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;android-toolchain/r16@dmerej/test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[settings]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;os&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;Android&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;os_build&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;os.api_level&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;compiler&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;clang&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;compiler.version&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;5.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[options]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;*:pic&lt;/span&gt; = &lt;span style=&#34;color:#ed9d13&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There we define all the common settings between all the Android configurations (like the API level, the compiler and the compiler version).&lt;/p&gt;
&lt;p&gt;Note the &lt;code&gt;*:pic&lt;/code&gt; in the &lt;code&gt;[options]&lt;/code&gt; section. This will make sure that everything is built with position independent code, a requirement for anything that runs on Android.&lt;/p&gt;
&lt;p&gt;Then if we need to build form &lt;code&gt;x86_64&lt;/code&gt;, we can invoke Conan this way:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan install --profile android --setting arch=x86_64
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All the settings from the android profile will be used, plus the &lt;code&gt;arch&lt;/code&gt; we just set on the command line.&lt;/p&gt;
&lt;h2 id=&#34;cross-compiling-sqlite3&#34;&gt;Cross compiling sqlite3&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#cross-compiling-sqlite3&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s cross-compile &lt;code&gt;sqlite3&lt;/code&gt; for Android:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan create . dmerej/test --profile android --setting arch=x86_64
sqlite3/3.21.0@dmerej/test: Exporting package recipe
...
Cross-build from &amp;#39;Linux:x86_64&amp;#39; to &amp;#39;Android:x86_64&amp;#39;
...
Requirements
    android-toolchain/r16@dmerej/stable
Packages
    android-toolchain/r16@dmerej/test
...
sqlite3/3.21.0@dmerej/test: Calling build()
-- Android: Targeting API &amp;#39;21&amp;#39; with
      architecture &amp;#39;x86_64&amp;#39;,
      ABI &amp;#39;x86_64&amp;#39;,
      and processor &amp;#39;x86_64&amp;#39;
...
sqlite3/3.21.0@dmerej/test: Package built
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Done :)&lt;/p&gt;
&lt;h2 id=&#34;cross-compiling-the-chucknorris-library&#34;&gt;Cross compiling the chucknorris library&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#cross-compiling-the-chucknorris-library&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s now try to build &lt;code&gt;ChuckNorris&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd cpp
$ mkdir -p build/android/x86_64
$ cd build/android/x86_64
$ conan install ../../.. --profile android --setting arch=x86_64
....
Cross-build from &amp;#39;Linux:x86_64&amp;#39; to &amp;#39;Android:x86_64&amp;#39;
sqlite3/3.21.0@dmerej/test: Already installed!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, now we are ready to build:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/android/x86_64
$ cmake -GNinja ../../..
$ ninja
-- The C compiler identification is GNU 7.3.0
-- The CXX compiler identification is GNU 7.3.0
-- Check for working C compiler: /bin/cc
-- Check for working C compiler: /bin/cc -- works
...
-- Check for working CXX compiler: /bin/c++
-- Check for working CXX compiler: /bin/c++ -- works
...
CMake Error at build/android/x86_64/conanbuildinfo.cmake:452 (message):
  Incorrect &amp;#39;clang&amp;#39;, is not the one detected by CMake: &amp;#39;GNU&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Uh-Oh: CMake is using the default compiler &lt;code&gt;/bin/cc&lt;/code&gt;. This is not going to work.&lt;/p&gt;
&lt;p&gt;But Conan knew how to cross-compile &lt;code&gt;sqlite3&lt;/code&gt; for Android! Can&amp;rsquo;t we tell Conan to build chucknorris too?&lt;/p&gt;
&lt;h2 id=&#34;creating-a-recipe-for-chucknorris&#34;&gt;Creating a recipe for chucknorris&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#creating-a-recipe-for-chucknorris&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Of course we can! Let&amp;rsquo;s go to &lt;code&gt;cpp/ChuckNorris&lt;/code&gt; and run &lt;code&gt;conan new&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan new ChuckNorris/0.1 --source
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then let&amp;rsquo;s edit the generated &lt;code&gt;conanfile.py&lt;/code&gt; to have:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;conans&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; ConanFile, CMake
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChucknorrisConan&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ChuckNorris&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    license = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;MIT&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    url = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://github.com/dmerejkowsky/chucknorris&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    description = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Chuck Norris does not need a description&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    settings = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiler&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build_type&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options = {&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    default_options = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shared=False&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    generators = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;cmake&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exports_sources = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;CMakeLists.txt&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;src/*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;include/*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;build&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake = CMake(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake.configure()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake.build()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;cpp_demo&amp;#34;&lt;/span&gt; dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;false&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that instead of having a &lt;code&gt;source()&lt;/code&gt; method to fetch the sources from a remote location (as we did for &lt;code&gt;sqlite3&lt;/code&gt;), we instead use &lt;code&gt;exports_sources&lt;/code&gt; to tell Conan about the sources it needs to build the package.&lt;/p&gt;
&lt;p&gt;Also note how we copy the &lt;code&gt;cpp_demo&lt;/code&gt; binary in the &lt;code&gt;package()&lt;/code&gt; method. We&amp;rsquo;ll use this to check that the binary we built with Conan can actually &lt;em&gt;run&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Then we create the chucknorris package:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd cpp/ChuckNorris
$ conan create .  dmere/test --profile android --setting arch=x86_64
ChuckNorris/0.1@dmerej/test: Exporting package recipe
...
Cross-build from &amp;#39;Linux:x86_64&amp;#39; to &amp;#39;Android:x86_64&amp;#39;
...
-- Build files have been written to: ...
../bin/clang++
  --target=x86_64-none-linux-android
  --gcc-toolchain=...
  -sysroot=...
  -isysroot=...
  -fPIC
  -fPIE -pie
  .../sqlite3.a
  ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Well, it did build, and the commands ran by Ninja closely resemble the ones we wrote by hand in the previous section.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s check it runs!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd ~/.conan/data/ChuckNorris/0.1/dmerej/test
$ cd package/&amp;lt;hash&amp;gt;/bin
$ adb push cpp_demo /data/local/tmp/
$ adb shell /data/local/tmp/cpp_demo
CANNOT LINK EXECUTABLE &amp;#34;/data/local/tmp/cpp_demo&amp;#34;:
  library &amp;#34;libc++_shared.so&amp;#34; not found
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What?&lt;/p&gt;
&lt;h2 id=&#34;the-libc-1&#34;&gt;The libc++&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-libc-1&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Remember when we talked about the &lt;code&gt;libc&lt;/code&gt;? Well, for &lt;code&gt;C++&lt;/code&gt; on Android there are two possible choices.&lt;/p&gt;
&lt;p&gt;You have to choose between the &lt;code&gt;gnustl&lt;/code&gt; library, or the &lt;code&gt;libc++&lt;/code&gt; library, and they both come in two flavors (static or shared).&lt;/p&gt;
&lt;p&gt;By default, our binary was compiled to link with shared version of &lt;code&gt;libc++&lt;/code&gt;, hence the file name: &lt;code&gt;libc++_shared.so&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Fortunately, we can use an other feature of Conan to help us: the &lt;code&gt;imports()&lt;/code&gt; function. This function gets called before building and can be used to copy files from the dependencies packages.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what we can do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;imports()&lt;/code&gt; to copy &lt;code&gt;libc++_shared.so&lt;/code&gt; from the &lt;code&gt;android-toolchain&lt;/code&gt; package to the build directory.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;keep_imports&lt;/code&gt; so that the imported files do not get removed from the build directory.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;copy()&lt;/code&gt; call in the &lt;code&gt;package()&lt;/code&gt; method so that the &lt;code&gt;libc++_shared.so&lt;/code&gt; file is present in the final package.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is known as &amp;ldquo;repackaging&amp;rdquo; in Conan parlance.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChucknorrisConan&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    keep_imports = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;imports&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;*libc++_shared.so&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bin/cpp_demo&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;bin&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.copy(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/libc++_shared.so&amp;#34;&lt;/span&gt;, dst=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&amp;#34;&lt;/span&gt;, keep_path=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can try again, using the &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; environment variable to tell the linker where to look for the shared libraries:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan create .  dmere/test --profile android --setting arch=x86_64
$ cd ~/.conan/data/ChuckNorris/0.1/dmerej/test
$ cd package/&amp;lt;hash&amp;gt;/
$ adb push bin/cpp_demo /data/local/tmp
$ adb push lib/libc++_shared.so /data/local/tmp/
$ adb shell
$ cd /data/local/tmp
$ LD_LIBRARY_PATH=lib ./cpp_demo
When a zombie apocalypse starts, Chuck Norris doesn&amp;#39;t try to survive.
The zombies do.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hooray!&lt;/p&gt;
&lt;p&gt;We can also check it works on a arm phone too:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd cpp/conan/android-toolchain
$ conan create . dmerej/test --profile android --setting arch=armv7
$ cd cpp/conan/sqlite3
$ conan create . dmerej/test --profile android --setting arch=armv7
$ cd cpp/ChuckNorris
$ conan create . dmerej/test --profile android --setting arch=armv7
$ cd ~/.conan/data/ChuckNorris/0.1/dmerej/test
# This would be a different hash since the settings have changed:
$ cd package/&amp;lt;hash&amp;gt;/
$ adb push bin/cpp_demo /data/local/tmp
$ adb push lib/libc++_shared.so /data/local/tmp/
$ adb shell
$ cd /data/local/tmp
$ LD_LIBRARY_PATH=lib ./cpp_demo
Giraffes were created when Chuck Norris uppercutted a horse.
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We finally managed to run some &lt;code&gt;C++&lt;/code&gt; code directly on Android.&lt;/p&gt;
&lt;p&gt;However, Android applications are written in Java (or Kotlin), so we still need to wrap the C++ library in Java.&lt;/p&gt;
&lt;p&gt;See you in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-7-android-jna/&#34;&gt;part 7&lt;/a&gt; for the next episode :)&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;You may be using other architectures without realizing it, but don&amp;rsquo;t worry too much about it.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;It&amp;rsquo;s actually a &lt;em&gt;good thing&lt;/em&gt;. Otherwise you won&amp;rsquo;t be able to run and debug the binaries you&amp;rsquo;ve just compiled.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Adventures in CI land</title>
      <link>https://dmerej.info/blog/post/adventures-in-ci-land/</link>
      <pubDate>Mon, 04 Jun 2018 18:21:30 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/adventures-in-ci-land/</guid>
      <description>&lt;p&gt;Today  at work I wrote a CI script to test a react application, and it turned out to be a bit trickier than expected.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try and reproduce the interesting issues I had and how I solved them.&lt;/p&gt;
&lt;h1 id=&#34;setting-the-stage&#34;&gt;Setting the stage&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#setting-the-stage&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s what you are going to need if you want to try and reproduce what I did.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node.js, yarn&lt;/li&gt;
&lt;li&gt;Python3 and &lt;code&gt;pipenv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;chromedriver&lt;/code&gt; binary.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s start by creating a simple React application:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ yarn global add create-react-app
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ create-react-app hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ &lt;span style=&#34;color:#24909d&#34;&gt;cd&lt;/span&gt; hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ yarn
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We now have a beautiful React application running in our favorite browser.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s edit the &lt;code&gt;App.js&lt;/code&gt; file to display &lt;code&gt;Hello, world&lt;/code&gt; instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; React, { Component } from &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;react&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; App &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extends&lt;/span&gt; Component {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  render() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &amp;lt;p&amp;gt;Hello, world!&amp;lt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;/p&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;default&lt;/span&gt; App;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;adding-some-end-to-end-tests&#34;&gt;Adding some end-to-end tests&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#adding-some-end-to-end-tests&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s use &lt;code&gt;pipenv&lt;/code&gt; to create a virtualenv with what we need:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pipenv install pytest
$ pipenv install selenium
$ pipenv shell
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now let&amp;rsquo;s add some end-to-end using selenium and pytest. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in test_hello.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;selenium.webdriver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_home&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    driver = selenium.webdriver.Chrome()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    driver.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;http://127.0.0.1:3000&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Hello, world!&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; driver.page_source
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now run the tests with pytest as usual:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pytest
collected 1 item

test_hello.py .                            [100%]
1 passed in 4.77 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, it works!&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s imagine you have a team of people working on the application, and you would like these tests to run any time someone creates a merge request on this repo.&lt;/p&gt;
&lt;p&gt;This is known as &lt;em&gt;continuous integration&lt;/em&gt; (CI for short) and, trust me on this, it works a lot better than telling your teammates to remember to run the tests before submitting their changes for review!&lt;/p&gt;
&lt;h1 id=&#34;writing-the-ci-script&#34;&gt;Writing the CI script&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#writing-the-ci-script&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We use &lt;code&gt;GitLab&lt;/code&gt; at work and are big fan of its CI features.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t know GitLab CI at all, here&amp;rsquo;s how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You install and configure the &lt;code&gt;gitlab-runner&lt;/code&gt; program on some machines (called &lt;em&gt;runners&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Then you write a &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file that contains the job description.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At my job we prefer to keep the &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; simple, and keep the code of the CI scripts separate, like this:&lt;/p&gt;
&lt;p&gt;(note how we use &lt;code&gt;python3 -m pipenv&lt;/code&gt; instead of just &lt;code&gt;pipenv&lt;/code&gt;. This is to make sure &lt;code&gt;pipenv&lt;/code&gt; runs with the expected version of Python)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in .gitlab-ci.yml&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;stages&lt;/span&gt;:&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;- check&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;check&lt;/span&gt;:&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;stage&lt;/span&gt;:&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;check&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;script&lt;/span&gt;:&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;- python3 -m pipenv install&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;- python3 -m pipenv run python ci.py&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in ci.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Call yarn here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; __name__ == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We do this because it makes it easy to reproduce build failures found during CI locally. Any developer on the team can run &lt;code&gt;python ci/ci.py&lt;/code&gt; on their machine directly instead of trying to copy/paste code from the yaml file.&lt;/p&gt;
&lt;h1 id=&#34;going-headless&#34;&gt;Going headless&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#going-headless&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Right now, the selenium tests use a full-fledged Chrome to run the tests. This is nice for the developers, but not so nice on a GitLab runner.&lt;/p&gt;
&lt;p&gt;It would be much better to have those running in a headless Chrome instead, i.e without any GUI.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s fix that by adding a &lt;code&gt;--headless&lt;/code&gt; option:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in conftest.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;pytest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;pytest_addoption&lt;/span&gt;(parser):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parser.addoption(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--headless&amp;#34;&lt;/span&gt;, action=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;store_true&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ffa500&#34;&gt;@pytest.fixture&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;headless&lt;/span&gt;(request):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; request.config.getoption(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--headless&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in test_hello.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;selenium.webdriver.chrome.options&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; Options &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;as&lt;/span&gt; ChromeOptions
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_home&lt;/span&gt;(headless):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;    options = ChromeOptions()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;    options.headless = headless
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;    driver = selenium.webdriver.Chrome(chrome_options=options)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now if we run &lt;code&gt;pytest&lt;/code&gt; with the &lt;code&gt;--headless&lt;/code&gt; option, the &lt;code&gt;headless&lt;/code&gt; parameter of the &lt;code&gt;test_home&lt;/code&gt; function will be set to &lt;code&gt;True&lt;/code&gt; by pytest.
That&amp;rsquo;s how pytest &lt;em&gt;fixtures&lt;/em&gt; work.&lt;/p&gt;
&lt;p&gt;Anyway, we can now check this is working by running:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ pytest --headless
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;writing-the-ci-script-1&#34;&gt;Writing the CI script&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#writing-the-ci-script-1&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So now we are faced with a new challenge: we need to run &lt;code&gt;yarn start&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; running &lt;code&gt;pytest&lt;/code&gt;, and kill the React script when the selenium tests have finished.&lt;/p&gt;
&lt;p&gt;A nice way to do this in Python is to use the &lt;code&gt;with&lt;/code&gt; statement, so let&amp;rsquo;s do that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;BackgroundProcess&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34; Run `yarn start` in the background. Ensure the yarn process
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    is killed when exiting the `with` block
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.process = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __enter__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.process = subprocess.Popen([&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yarn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __exit__(self, &lt;span style=&#34;color:#24909d&#34;&gt;type&lt;/span&gt;, value, tb):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.process.terminate()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;with&lt;/span&gt; BackgroundProcess(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;yarn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        subprocess.run([&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;pytest&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;--headless&amp;#34;&lt;/span&gt;], check=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; __name__ == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;__enter__&lt;/code&gt; method will be called right before the contents of the &lt;code&gt;with&lt;/code&gt; block, so before &lt;code&gt;pytest&lt;/code&gt; starts.
Then the &lt;code&gt;__exit__&lt;/code&gt; method will be called after &lt;code&gt;pytest&lt;/code&gt; is done, &lt;em&gt;even if an exception occurred&lt;/em&gt;, passing data about the exception as arguments to the &lt;code&gt;__exit__()&lt;/code&gt; method. Since we don&amp;rsquo;t want do to anything other than re-raise if this happens, we just ignore them.&lt;/p&gt;
&lt;p&gt;Anyway, this is much more readable than using &lt;code&gt;try/except/finally&lt;/code&gt;, don&amp;rsquo;t you think?&lt;/p&gt;
&lt;p&gt;We still need a tiny fix: by default, &lt;code&gt;yarn start&lt;/code&gt; will open a new tab on our browser. This was great while we were working on the JavaScript code, but here we are working on the CI script, so we&amp;rsquo;d prefer to disable this behavior.&lt;/p&gt;
&lt;p&gt;Fortunately, all we have to do is to set the &lt;code&gt;BROWSER&lt;/code&gt; environment variable to &lt;code&gt;NONE&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;BackgroundProcess&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __enter__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        env = os.environ.copy()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        env[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;BROWSER&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;NONE&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.process = subprocess.Popen(self.cmd, env=env)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: you may wonder why we did not just set the &lt;code&gt;BROWSER&lt;/code&gt; environment variable directly in the &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; file. This would have worked, but here we create a special &lt;em&gt;copy&lt;/em&gt; of the current environment variables, and we set the &lt;code&gt;BROWSER&lt;/code&gt; environment variable &lt;em&gt;just for the &lt;code&gt;yarn&lt;/code&gt; process&lt;/em&gt;. Why?&lt;/p&gt;
&lt;p&gt;Well, if you think of environment variables as nasty global variables (and you should: the environment of a process is just a big mutable shared state), it makes sense to limit their scope this way.&lt;/p&gt;
&lt;p&gt;Anyway, back to the main topic:&lt;/p&gt;
&lt;h1 id=&#34;the-bug&#34;&gt;The bug&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-bug&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&#34;note&#34;&gt;
  The rest of the article assumes you are using Linux. Things may work a bit differently (or not at all) on other operating systems.
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s see if the CI script works.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python ci.py
yarn run v1.7.0
$ react-scripts start
Starting the development server...
...
1 passed in 4.77 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s run it a second time just to check that the &lt;code&gt;yarn&lt;/code&gt; process was indeed killed:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python ci.py
? Something is already running on port 3000. Probably:
  hello (pid 16508)

Would you like to run the app on another port instead? (Y/n)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Uh-oh.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s run &lt;code&gt;pgrep&lt;/code&gt; to check that the &lt;code&gt;yarn&lt;/code&gt; process is dead:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pgrep yarn
[err 1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The yarn process &lt;em&gt;is&lt;/em&gt; dead. What gives ?&lt;/p&gt;
&lt;p&gt;If we take a look at the &lt;code&gt;.terminate()&lt;/code&gt; implementation, here&amp;rsquo;s what we find:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in /usr/lib/python3.6/subprocess.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Popen&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;send_signal&lt;/span&gt;(self, sig):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Send a signal to the process.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Skip signalling a process that we know has already died.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.returncode &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              os.kill(self.pid, sig)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;terminate&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;Terminate the process with SIGTERM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;          &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          self.send_signal(signal.SIGTERM)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, &lt;code&gt;terminate()&lt;/code&gt; just sends the &lt;code&gt;SIGTERM&lt;/code&gt; signal using the process ID (&lt;code&gt;pid&lt;/code&gt;). The bug&amp;rsquo;s not there.&lt;/p&gt;
&lt;h1 id=&#34;the-naked-truth&#34;&gt;The naked truth&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-naked-truth&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The truth is we&amp;rsquo;ve just created an orphan (we&amp;rsquo;re monsters!)&lt;/p&gt;
&lt;p&gt;When we ran &lt;code&gt;yarn start&lt;/code&gt;, the &lt;code&gt;yarn&lt;/code&gt; process looked at a section named &lt;code&gt;start&lt;/code&gt; in the &lt;code&gt;package.json&lt;/code&gt; and found something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;react-scripts start&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It then created a &lt;em&gt;child&lt;/em&gt; process, namely &lt;code&gt;react-scripts start&lt;/code&gt;, with a &lt;em&gt;different PID&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So when we killed the parent process, the &lt;code&gt;node&lt;/code&gt; process became an orphan since its parent was dead (poor little process).&lt;/p&gt;
&lt;p&gt;On Linux at least, all orphans process get automatically re-attached to the first ever process that was created since the machine booted. (&lt;code&gt;systemd&lt;/code&gt; on my machine). This process always has a PID equal to 1 and is often referred to as &lt;code&gt;init&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can check that by running &lt;code&gt;pstree&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pstree
systemd─┬                               &amp;lt;- PID 1
...
        ├─node──                        &amp;lt;- our poor orphan
...
        ├─plasmashell─┬
                      ├─konsole─┬─zsh─  &amp;lt;- our shell
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So how do we make sure the &lt;code&gt;node&lt;/code&gt; child process gets killed too?&lt;/p&gt;
&lt;p&gt;There are some fancy ways to fix these kind of problems (we could use &lt;code&gt;cgroups&lt;/code&gt; for instance), but we can do it just with the Python stdlib.&lt;/p&gt;
&lt;p&gt;Turns out we can use the &lt;code&gt;start_new_session&lt;/code&gt; argument in the &lt;code&gt;subprocess.Popen()&lt;/code&gt; call. This will create a &lt;em&gt;session&lt;/em&gt; and attach the &lt;code&gt;yarn&lt;/code&gt; process (and all its children) to it.&lt;/p&gt;
&lt;p&gt;Then we can send the &lt;code&gt;SIGTERM&lt;/code&gt; signal to the PID of the parent, and all the processes in the session will receive it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;signal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __enter__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;  self.process = subprocess.Popen(self.cmd, start_new_session=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __exit__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;    os.killpg(self.process.pid, signal.SIGTERM)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now if we re-run our script, we can see that neither &lt;code&gt;yarn&lt;/code&gt; or &lt;code&gt;node&lt;/code&gt; remain alive when the CI script terminates:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python ci.py
$ pgrep yarn
[err 1]
$ pgrep node
[err 1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&amp;rsquo;s all for today. Cheers!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;This is not the first time I&amp;rsquo;ve used those tools to write end-to-end tests for Web application. See &lt;a href=&#34;https://dmerej.info/blog/post/porting-to-pytest-a-practical-example/&#34;&gt;Porting to pytest&lt;/a&gt; for instance.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>I don&#39;t need types</title>
      <link>https://dmerej.info/blog/post/i-dont-need-types/</link>
      <pubDate>Sun, 27 May 2018 10:17:17 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/i-dont-need-types/</guid>
      <description>&lt;p&gt;This is a story about me being wrong about tests and type systems.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also a story of me trying something new and learning a few things.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start at the beginning.&lt;/p&gt;
&lt;h1 id=&#34;c-vs-python&#34;&gt;C++ vs Python&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#c-vs-python&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A few years ago, I was working in a team where the two main languages used were C++ and Python.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what I used to think:&lt;/p&gt;
&lt;p&gt;C++ sucks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I have to specify types everywhere:
&lt;ul&gt;
&lt;li&gt;I need to know the difference between &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;uin8_t&lt;/code&gt;, &lt;code&gt;size_t&lt;/code&gt; even if all I want is a goddamn integer.&lt;/li&gt;
&lt;li&gt;I have to duplicate the signatures of the methods and functions in the header and the source files&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I never know if a compiler warning or error indicates a bug or not&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s still a lot of bugs the compiler does not catch (race conditions, dangling pointers &amp;hellip;.)&lt;/li&gt;
&lt;li&gt;Refactoring is hard: when you change a function signature, you have to fix the code everywhere before you can even run some tests.&lt;/li&gt;
&lt;li&gt;Writing tests in hard: You can&amp;rsquo;t really write isolation tests because mocking and dependency injection in C++ don&amp;rsquo;t really work. Plus, &lt;code&gt;gtest&lt;/code&gt; sucks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python rocks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don&amp;rsquo;t have to think about types if I don&amp;rsquo;t want to. If I &lt;em&gt;really&lt;/em&gt; need it, I can write an abstract base class, but most of the time duck-typing &amp;ldquo;just works&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t need compile-time checks because if I misspell a variable or function name, or if I forgot to import a module, I&amp;rsquo;ll get a test failure immediately.&lt;/li&gt;
&lt;li&gt;For each bug I can quickly add a non-regression test.&lt;/li&gt;
&lt;li&gt;Refactoring is easy: all you have to do is run the tests, look at the failures and fix the code. When the tests pass, you know you&amp;rsquo;re done.&lt;/li&gt;
&lt;li&gt;Writing tests is easy: dependency injection is trivial thanks to duck-typing, and you can monkey-patch or mock everything! Plus, &lt;code&gt;pytest&lt;/code&gt; is awesome!&lt;/li&gt;
&lt;li&gt;Static analysis for Python does not work, pylint is slow, and hard to configure. There are tons of bugs it does not catch, and it is often wrong.&lt;/li&gt;
&lt;li&gt;Types annotations are useless (after all, the interpreter does almost nothing with them), except maybe for documentation purposes.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;note&#34;&gt;
  I now think &lt;strong&gt;most of these statements are wrong&lt;/strong&gt;, but it was what I believed at the time.
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;h1 id=&#34;changing-my-mind&#34;&gt;Changing my mind&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#changing-my-mind&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;So there I was. Tools and type systems did not matter, all that matter were tests and how easy it was to write them. I did not need a type system because tests were enough.&lt;/p&gt;
&lt;center&gt;⁂&lt;/center&gt;
&lt;p&gt;Boy, was I wrong&amp;hellip; Here&amp;rsquo;s a list of things that contributed to burst my bubble.&lt;/p&gt;
&lt;h2 id=&#34;some-linters&#34;&gt;Some linters&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#some-linters&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&#34;pyflakes&#34;&gt;pyflakes&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#pyflakes&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I started using &lt;a href=&#34;https://github.com/PyCQA/pyflakes&#34;&gt;pyflakes&lt;/a&gt; with &lt;a href=&#34;https://github.com/w0rp/ale&#34;&gt;vim-ale&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;pyflakes is very easy to use, requires no configuration and is fast.&lt;/p&gt;
&lt;p&gt;Suddenly a whole bunch of bugs disappeared: pyflakes is very good at finding misspelled variables or missing imports.&lt;/p&gt;
&lt;p&gt;So maybe writing tests just to find misspelled variables or missing imports is overkill?&lt;/p&gt;
&lt;p&gt;Of course, pyflakes does not catch other errors like calling a function with an incorrect number of arguments but still, it&amp;rsquo;s quite nice to catch these errors &lt;em&gt;right after the file is saved&lt;/em&gt;, instead of later when a test fails.&lt;/p&gt;
&lt;h3 id=&#34;pylint&#34;&gt;pylint&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#pylint&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve already mentioned how &lt;a href=&#34;https://dmerej.info/blog/post/some-pylint-tips/&#34;&gt;pylint can be very useful&lt;/a&gt; if you take the time to configure it properly, so I won&amp;rsquo;t repeat myself here.&lt;/p&gt;
&lt;p&gt;Still, I learned that Python static analyzers did not have to suck after all, and could find defects faster than tests.&lt;/p&gt;
&lt;p&gt;Today I use pyflakes, pylint and a few other linters for all my Python projects. You can read more about this in
&lt;a href=&#34;https://dmerej.info/blog/post/how-i-lint/&#34;&gt;How I lint my Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At this point I had changed my mind a little bit. They were tools other than tests that could be useful. But I was still thinking that types did not help nearly as much as tests did.&lt;/p&gt;
&lt;h2 id=&#34;a-talk&#34;&gt;A talk&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-talk&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;And then I watched a talk called &lt;a href=&#34;https://www.destroyallsoftware.com/talks/ideology&#34;&gt;ideology&lt;/a&gt;, by Gary Bernhardt. I highly recommend it.&lt;/p&gt;
&lt;p&gt;Excerpt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[This is important] mostly because it will make you better programmers, but also because it will stop you from making angry Hacker News comments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I won&amp;rsquo;t summarize the talk here, but it helped me realizing what I really meant when I claimed &amp;ldquo;I have tests so I don&amp;rsquo;t need types&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;But this was rather abstract. Changing my mind about tests required me working
with programming languages other than C++ and Python.&lt;/p&gt;
&lt;h2 id=&#34;javascript&#34;&gt;JavaScript&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#javascript&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Last year I had to make a refactoring in a JavaScript project.&lt;/p&gt;
&lt;p&gt;There were &lt;em&gt;no tests at all&lt;/em&gt;, and adding them would have been pretty challenging.&lt;/p&gt;
&lt;p&gt;But there were &lt;a href=&#34;https://flow.org/&#34;&gt;flow&lt;/a&gt; type annotations everywhere. The errors weren&amp;rsquo;t
always easy to understand and even sometimes misleading, but flow did help me gain
confidence that I was not breaking everything during the refactoring.&lt;/p&gt;
&lt;p&gt;That showed me that type annotations in a &amp;ldquo;dynamic&amp;rdquo; languages could actually be worth it.&lt;/p&gt;
&lt;p&gt;Still, I was convinced we should have written tests for this project since day one, and not let
the production code grow without tests.&lt;/p&gt;
&lt;p&gt;Type annotations were required &lt;em&gt;because&lt;/em&gt; they were no tests, and surely tests alone would have suffice.&lt;/p&gt;
&lt;h2 id=&#34;rust&#34;&gt;Rust&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#rust&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Rust was the last nail in the coffin.&lt;/p&gt;
&lt;p&gt;I started re-writing a Python project in Rust, and suddenly all this stuff
about &amp;ldquo;if it compiles, it works&amp;rdquo;, and &amp;ldquo;types system make unit tests
unnecessary&amp;rdquo; finally started to make sense.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what I learned using Rust:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specifying types is easy: all you need to annotate are function parameters and
return values, and everything else is inferred by the compiler.&lt;/li&gt;
&lt;li&gt;Error messages and warnings almost always indicate a bug or an inefficient way of doing things.&lt;/li&gt;
&lt;li&gt;And types can actually help you!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let me give you a few examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anything that can fail returns a &lt;em&gt;type&lt;/em&gt; (like &lt;code&gt;Option&lt;/code&gt; or &lt;code&gt;Result&lt;/code&gt;) that
forces you to handle errors.&lt;/li&gt;
&lt;li&gt;There is a &lt;code&gt;Copy&lt;/code&gt; &lt;em&gt;trait&lt;/em&gt; that tells you whether a type has copy semantics versus move semantics.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Send&lt;/code&gt; and &lt;code&gt;Sync&lt;/code&gt; traits define how you can use a type across threads.&lt;/li&gt;
&lt;li&gt;and more!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the mean time, using TDD with Rust is enjoyable and even recommended in &lt;a href=&#34;https://doc.rust-lang.org/stable/book/second-edition/index.html&#34;&gt;the Rust book&lt;/a&gt;.
I even wrote a test to make sure a certain bug would be caught &lt;em&gt;at compile time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s how I completely changed my mind: type system do not have to suck,
they can be very useful, and you can &lt;em&gt;combine&lt;/em&gt; them with tests to get the
best of two worlds.&lt;/p&gt;
&lt;h1 id=&#34;conclusion-and-teaser&#34;&gt;Conclusion and teaser&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion-and-teaser&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You see, we are terrible at spotting errors in our own code.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why we try and multiply the techniques hoping each of them will find different types of mistakes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We ask other humans to look at our code, during code reviews or peer programming&lt;/li&gt;
&lt;li&gt;We ask other humans to find defects in the code for us, and we call this &amp;ldquo;a QA process&amp;rdquo;&lt;/li&gt;
&lt;li&gt;We use static analyzers to find issues in the code automatically&lt;/li&gt;
&lt;li&gt;We use tests to try and prove that the code works as it should&lt;/li&gt;
&lt;li&gt;We use TDD to look at the code both from the &amp;lsquo;production&amp;rsquo; perspective (when we go from red to green), and from a &amp;lsquo;quality&amp;rsquo; perspective (when we go from green to refactor).&lt;/li&gt;
&lt;li&gt;And we use static types or type annotations to improve correctness of the
code in a way that complements all of the above methods.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all for today.&lt;/p&gt;
&lt;p&gt;If you still believe that Python does not need types if you have a good tests, I&amp;rsquo;ll have some very concrete examples to show you in a &lt;a href=&#34;https://dmerej.info/blog/post/giving-mypy-a-go/&#34;&gt;future blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;If using this kind of linters sounds interesting to you, you can read my &lt;a href=&#34;https://dmerej.info/blog/post/lets-have-a-pint-of-vim-ale/&#34;&gt;blog post&lt;/a&gt; on the subject.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>A boolean&#39;s story</title>
      <link>https://dmerej.info/blog/post/a-booleans-story/</link>
      <pubDate>Fri, 18 May 2018 13:50:38 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/a-booleans-story/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/introducing-rusync/&#34;&gt;Earlier this month&lt;/a&gt; I told you
about my pet project in Rust.&lt;/p&gt;
&lt;p&gt;As a reminder, it&amp;rsquo;s a tool named rusync which contains some of the
functionality offered by the &lt;code&gt;rsync&lt;/code&gt; command-line tool.&lt;/p&gt;
&lt;p&gt;Today I&amp;rsquo;d like to talk about a feature I&amp;rsquo;ve added recently, and take this
opportunity to show you a few principles of good design along the way.&lt;/p&gt;
&lt;p&gt;You can find the code on &lt;a href=&#34;https://github.com/dmerejkowsky/rusync&#34;&gt;github&lt;/a&gt; and
download it from &lt;a href=&#34;https://crates.io/crates/rusyn://crates.io/crates/rusync&#34;&gt;crates.io&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;the-algorithm&#34;&gt;The algorithm&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-algorithm&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;You run rusync by calling it with a source and destination directory, like so:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ rusync src dest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The algorithm is pretty straightforward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Recurse through all directories and files in the &lt;code&gt;src&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;For each source file (for instance &lt;code&gt;src/foo/bar.txt&lt;/code&gt;), check if the destination file
(&lt;code&gt;dest/foo/bar.txt&lt;/code&gt; in this case) exists. If it &lt;em&gt;does&lt;/em&gt; exist, get its &lt;code&gt;mtime&lt;/code&gt; (that is, the
date it was last modified). Then, if the source is more recent than the destination, or if
the destination is missing, proceed and copy the whole contents of
&lt;code&gt;src/foo/bar.txt&lt;/code&gt; to &lt;code&gt;dest/foo/bar.txt&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One of the issues I had to deal with is the preservation of permissions.
Suppose one of the files is executable, let&amp;rsquo;s say &lt;code&gt;src/foo/bar.exe&lt;/code&gt;, then the
destination (&lt;code&gt;dest/foo/bar.exe&lt;/code&gt;) should be executable too.&lt;/p&gt;
&lt;p&gt;So, after the destination file has been written, we should apply the necessary
transformations so that the permissions of the destination file match the
permissions of the source file.&lt;/p&gt;
&lt;h1 id=&#34;the-code&#34;&gt;The code&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-code&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s what the implementation looked like at the time.&lt;/p&gt;
&lt;div class=&#34;note&#34;&gt;
  There&amp;rsquo;s a bug waiting to happen in the following code, can you find it ?
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s start by &lt;code&gt;main()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[derive(Debug, StructOpt)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(name = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;rusync&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Opt&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(parse(from_os_str))]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;source: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;PathBuf&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(parse(from_os_str))]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;destination: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;PathBuf&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Opt::from_args();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;source&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;opt.source;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;destination&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;opt.destination;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;syncer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Syncer::new(&amp;amp;source,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;destination);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;syncer.sync()?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We declare a struct &lt;code&gt;Opt&lt;/code&gt; which will contain our command line options, then in
&lt;code&gt;main()&lt;/code&gt; we parse the command line arguments and instantiate a new &lt;code&gt;Syncer&lt;/code&gt;
object.&lt;/p&gt;
&lt;p&gt;Here are the relevant parts of the &lt;code&gt;Syncer&lt;/code&gt; implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Syncer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(source: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Path&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;destination: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Path&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Syncer&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Syncer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;source: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;source&lt;/span&gt;.to_path_buf(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;destination: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;destination&lt;/span&gt;.to_path_buf(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;sync&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;top_dir&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;self.source.clone();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.walk_dir(top_dir)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;walk_dir&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;subdir: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Path&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;fs::read_dir(subdir)?&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry.path();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;path.is_dir()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;subdir&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;path;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;self.walk_dir(&amp;amp;subdir)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                &lt;/span&gt;self.sync_file(&amp;amp;entry)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;sync_file&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;DirEntry&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;rel_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;get_rel_path(&amp;amp;entry.path(),&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;self.source)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;parent_rel_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;rel_path.parent();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;to_create&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.destination.join(parent_rel_path);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;fs::create_dir_all(to_create)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry::Entry::new(&amp;amp;desc,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;entry.path());&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.destination.join(&amp;amp;rel_path);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest_entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry::Entry::new(&amp;amp;desc,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest_path);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;fsops::sync_entries(&amp;amp;src_entry,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest_entry)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, the bulk of the work is done by the &lt;code&gt;sync_file&lt;/code&gt; function, which
calls &lt;code&gt;fsops::sync_entries&lt;/code&gt; with a &lt;code&gt;Entry&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Entry&lt;/code&gt; type is a container for the file path and its metadata. Reading metadata
about the file (such as its &lt;code&gt;mtime&lt;/code&gt;) is expensive, so we do that once in the
&lt;code&gt;Entry::new()&lt;/code&gt; function and the rest of the code can then use the public functions of the &lt;code&gt;Entry&lt;/code&gt; struct to retrieve info about the file in question.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;path: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;PathBuf&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;metadata: &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;fs::Metadata&amp;gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;exists: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(description: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;str&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry_path: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Path&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;metadata&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;fs::metadata(entry_path).ok();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Entry&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;metadata: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;metadata&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;path: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;entry_path&lt;/span&gt;.to_path_buf(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;exists: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;entry_path&lt;/span&gt;.exists(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;path&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;PathBuf&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;self.path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;exists&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt; {&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self.exists&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;metadata&lt;/span&gt;(&amp;amp;self)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#24909d&#34;&gt;Option&lt;/span&gt;&amp;lt;&amp;amp;fs::Metadata&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.metadata.as_ref()&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, let&amp;rsquo;s take a look at the &lt;code&gt;sync_entries&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;BUFFER_SIZE&lt;/span&gt;: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;usize&lt;/span&gt; =&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;*&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;1024&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;sync_entries&lt;/span&gt;(src: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;more_recent&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;more_recent_than(&amp;amp;src,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;more_recent&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;copy_entry(&amp;amp;src,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;copy_entry&lt;/span&gt;(src: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src.path();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_file&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;File::open(src_path)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest_file&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;File::create(dest_path)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;buffer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;vec![&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#40ffff&#34;&gt;BUFFER_SIZE&lt;/span&gt;];&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;num_read&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_file.read(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;buffer)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;num_read&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;==&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;break&lt;/span&gt;;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;dest_file.write(&amp;amp;buffer[&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;..num_read])?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;copy_perms(&amp;amp;src,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;copy_perms&lt;/span&gt;(src: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_meta&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;src.metadata();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_meta&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;src_meta.expect(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;src_meta was None&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;permissions&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_meta.permissions();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest_file&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;File::create(dest.path())?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;dest_file.set_permissions(permissions)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, the &lt;code&gt;sync_entries&lt;/code&gt; function takes care of copying the source
file contents to the dest file chunk by chunk, and then calls &lt;code&gt;copy_perms()&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;a-new-option&#34;&gt;A new option&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-new-option&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;After a while, it occurred to me that rusync will be annoying to use in case we
copy from an &lt;code&gt;ext4&lt;/code&gt; partition to a &lt;code&gt;fat32&lt;/code&gt; partition.&lt;/p&gt;
&lt;p&gt;Indeed, Linux cannot set permissions on a &lt;code&gt;fat32&lt;/code&gt; partitions, so the code from
&lt;code&gt;copy_perms&lt;/code&gt; would surely fail in this case.&lt;/p&gt;
&lt;p&gt;I decided what I needed was a flag on the command line so that users of rusync
could choose to turn off the &amp;ldquo;copy permissions&amp;rdquo; feature.&lt;/p&gt;
&lt;p&gt;Well, this does not seem to hard, does it ? We just need to pass around a
boolean called &lt;code&gt;preserve_permissions&lt;/code&gt;  all the way from the &lt;code&gt;Opt&lt;/code&gt; struct in
&lt;code&gt;main&lt;/code&gt; to the &lt;code&gt;sync_entries&lt;/code&gt; in function, across the &lt;code&gt;Syncer&lt;/code&gt; struct.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s do that!&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s adapt &lt;code&gt;main.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Opt&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#[structopt(long = &lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;no-perms&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;)]&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;no_preserve_permissions: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;opt&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Opt::from_args();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;source&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;opt.source;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;destination&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;opt.destination;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;preserve_permissions&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;!opt.no_preserve_permissions;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;syncer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Syncer::new(&amp;amp;source,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;destination);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;syncer.preserve_permissions(preserve_permissions);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then let&amp;rsquo;s adapt the &lt;code&gt;Syncer&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;Syncer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;new&lt;/span&gt;(source: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Path&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;destination: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Path&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Syncer&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;Syncer&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;source: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;source&lt;/span&gt;.to_path_buf(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;destination: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;destination&lt;/span&gt;.to_path_buf(),&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;            &lt;/span&gt;preserve_permissions: &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;true&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;preserve_permissions&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;preserve_permissions: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;self.preserve_permissions&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;preserve_permissions;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;sync_file&lt;/span&gt;(&amp;amp;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;self,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;entry: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;DirEntry&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;fsops::sync_entries(&amp;amp;src_entry,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest_entry,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;preserve_permissions);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And then let&amp;rsquo;s adapt &lt;code&gt;sync_entries&lt;/code&gt; and &lt;code&gt;copy_entry&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;copy_entry&lt;/span&gt;(src: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                   &lt;/span&gt;preserve_permissions: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;,)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt;  &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;more_recent&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;more_recent_than(&amp;amp;src,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;more_recent&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;copy_entry(&amp;amp;src,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;preserve_permissions);&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;Ok&lt;/span&gt;(())&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;copy_entry&lt;/span&gt;(src: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;dest: &lt;span style=&#34;color:#6ab825&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Entry&lt;/span&gt;,&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;                  &lt;/span&gt;preserve_permissions: &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;bool&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;io&lt;/span&gt;::&lt;span style=&#34;color:#24909d&#34;&gt;Result&lt;/span&gt;&amp;lt;()&amp;gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_path&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src.path();&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;src_file&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;File::open(src_path)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;preserve_permissions&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;      &lt;/span&gt;copy_perms(&amp;amp;src,&lt;span style=&#34;color:#666&#34;&gt; &lt;/span&gt;&amp;amp;dest)?;&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex; background-color:#363636&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#666&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we run the tests, and it looks like nothing broke. Hooray!&lt;/p&gt;
&lt;h1 id=&#34;time-for-refactoring&#34;&gt;Time for refactoring&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#time-for-refactoring&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;There are several things we can change to make the code more readable.&lt;/p&gt;
&lt;p&gt;First, we can get rid of the double negative in &lt;code&gt;main.rs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;impl Opt {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;struct Opt {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    #[structopt(long = &amp;#34;no-perms&amp;#34;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    no_preserve_permissions: bool,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    // ..
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ impl Opt {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+     fn preserve_permissions(&amp;amp;self) -&amp;gt; bool {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+         !self.no_preserve_permissions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+     }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fn main() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    let opt = Opt::from_args();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    let source = &amp;amp;opt.source;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    let destination = &amp;amp;opt.destination;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   let preserve_permissions = !opt.no_preserve_permissions;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   let preserve_permissions = opt.preserve_permissions();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;    let mut syncer = Syncer::new(&amp;amp;source, &amp;amp;destination);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    syncer.preserve_permissions(preserve_permissions);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yeah, I know it&amp;rsquo;s a little change, but it&amp;rsquo;s the kind of little details that
matter in the long run. Double negatives are just as hard to understand in
plain English as in code.&lt;/p&gt;
&lt;p&gt;Then we have all these functions that take a boolean parameter.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&#34;https://blog.cleancoder.com/&#34;&gt;Uncle Bob&lt;/a&gt; would tell you, whenever you have
a function that takes a boolean, you almost always want two functions instead.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s think about our &lt;code&gt;preserve_permissions&lt;/code&gt; boolean.&lt;/p&gt;
&lt;p&gt;Turns out we can split &lt;code&gt;sync_entries&lt;/code&gt; in two. One that only does the copy, and
the other one that deals with permissions preservation.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll keep the &lt;code&gt;preserve_permission&lt;/code&gt; field in the &lt;code&gt;Syncer&lt;/code&gt;, and only call the
second function if we need to.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at the patch:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- pub fn copy_entry(src: &amp;amp;Entry, dest: &amp;amp;Entry,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-                   preserve_permissions: bool,) -&amp;gt; io::Result&amp;lt;()&amp;gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ pub fn copy_entry(src: &amp;amp;Entry, dest: &amp;amp;Entry) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  // ..
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    if preserve_permissions {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        copy_permissions(&amp;amp;src, &amp;amp;dest);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;  Ok(())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- pub fn sync_entries(src: &amp;amp;Entry, dest: &amp;amp;Entry,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-                      preserve_permissions: bool) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ pub fn sync_entries(src: &amp;amp;Entry, dest: &amp;amp;Entry) -&amp;gt; io::Result&amp;lt;(SyncOutcome)&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;     if more_recent {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        return copy_entry(&amp;amp;src, &amp;amp;dest, preserve_permissions);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+        return copy_entry(&amp;amp;src, &amp;amp;dest);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;impl Syncer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fn sync_file(*mut self, entry: &amp;amp;DirEntry) -&amp;gt; io::Result&amp;lt;()&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         let dest_path = self.destination.join(&amp;amp;rel_path);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        fsops::sync_entries(&amp;amp;src_entry, &amp;amp;dest_entry, self.preserve_permissions)?;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+        fsops::sync_entries(&amp;amp;src_entry, &amp;amp;dest_entry)?;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+        if self.preserve_permissions {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+            fsops::copy_permissions(&amp;amp;src_entry, &amp;amp;dest_entry)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+          }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It seems we just moved the logic about permissions preservation from the low-level
&lt;code&gt;fsops&lt;/code&gt; module, to the high-level &lt;code&gt;Syncer&lt;/code&gt; module, but the consequences of this refactoring
may be more profound than you think.&lt;/p&gt;
&lt;h1 id=&#34;a-new-design&#34;&gt;A new design&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#a-new-design&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Note how the functions in &lt;code&gt;fsops&lt;/code&gt; now know &lt;em&gt;nothing&lt;/em&gt; about the command-line flags.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s us trying to adhere to Single Responsibility Principle. The &lt;abbr
title=&#34;Single Responsibility Principle&#34;&gt;SRP&lt;/abbr&gt; more or less states that
each module should only have one reason to change.&lt;/p&gt;
&lt;p&gt;Code in &lt;code&gt;syncer.rs&lt;/code&gt; will have to change if we want to customize the &lt;em&gt;behavior&lt;/em&gt; of &lt;code&gt;rusync&lt;/code&gt;
(like deleting the extraneous files in the destination folder). On the other hand, code in
&lt;code&gt;fsops.rs&lt;/code&gt; will have to change if we want to modify low-level &lt;em&gt;implementation&lt;/em&gt; details of &lt;code&gt;rusync&lt;/code&gt;
(like using a more efficient algorithm like rsync does).&lt;/p&gt;
&lt;p&gt;Note that in the first case, we&amp;rsquo;ll of course have to add code in &lt;code&gt;fsops.rst&lt;/code&gt; to
delete files or directories, but we are OK with it because the code will
likely don&amp;rsquo;t have to be &lt;em&gt;modified&lt;/em&gt;, we&amp;rsquo;ll just have to &lt;em&gt;add more functions&lt;/em&gt;.
(That&amp;rsquo;s an other principle at play here called the Open/Close Principle).&lt;/p&gt;
&lt;p&gt;Anyway, found the bug yet?&lt;/p&gt;
&lt;h1 id=&#34;the-bug&#34;&gt;The bug&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-bug&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I actually discovered the &amp;ldquo;bug waiting to happen&amp;rdquo; I talked about in the
beginning when I re-ran the test suite after I performed
the refactoring I just discussed. One of the tests started failing.&lt;/p&gt;
&lt;p&gt;Can you try and find it just by looking at the patches above ?&lt;/p&gt;
&lt;div class=&#34;note&#34;&gt;
  There is a clue about the bug in one of the previous post of this blog.
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;p&gt;If you want to find out, click on the &amp;ldquo;spoiler&amp;rdquo; below.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;&lt;strong&gt;Toggle Spoiler&lt;/strong&gt;&lt;/summary&gt;
  &lt;p&gt;
  &lt;p&gt;It&amp;rsquo;s the same kind of bug I mentioned in the &lt;a href=&#34;https://dmerej.info/blog/post/non-isomorphic-cpp-refactoring/&#34;&gt;non-isomorphic C++ refactoring
article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You see, in Rust some types implement the &lt;code&gt;Drop&lt;/code&gt; trait, and have a &lt;code&gt;.drop()&lt;/code&gt;
method called when they go out of scope.&lt;/p&gt;
&lt;p&gt;In our case, &lt;em&gt;before&lt;/em&gt; our refactoring, the dest file was created twice. Once in
the &lt;code&gt;copy_entry()&lt;/code&gt; function, and an other time in the &lt;code&gt;copy_perms()&lt;/code&gt; function.
Usually, &lt;code&gt;File::create&lt;/code&gt; truncates the file, but when the first file handle was
destroyed, its contents were magically preserved. (Software is weird sometimes)&lt;/p&gt;
&lt;p&gt;After the refactoring, the second &lt;code&gt;File:;create()&lt;/code&gt; was called after the first
file handle was closed, and the destination filed ended up empty (but with the
correct permissions &amp;hellip;)&lt;/p&gt;

  &lt;/p&gt;
&lt;/details&gt;

</description>
    </item>
    
    <item>
      <title>Introducing rusync</title>
      <link>https://dmerej.info/blog/post/introducing-rusync/</link>
      <pubDate>Tue, 08 May 2018 17:59:06 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/introducing-rusync/</guid>
      <description>&lt;p&gt;Today I wrote my first &amp;ldquo;real&amp;rdquo; rust project.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a re-write of &lt;code&gt;rsync&lt;/code&gt; in Rust called &lt;code&gt;rusync&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what its installation and usage look like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cargo install rusync
$ rusync test/src test/dest
:: Syncing from test/src to test/dest …
-&amp;gt; foo/baz.txt
-&amp;gt; foo/bar.txt
 ✓ Synced 2 files (1 up to date)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can find the sources &lt;a href=&#34;https://github.com/dmerejkowsky/rusync&#34;&gt;on github&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;feedback-request&#34;&gt;Feedback request&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#feedback-request&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I wrote this because I wanted to give Rust a try.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re already are a Rust developer, I&amp;rsquo;d appreciate it if you could give me a honest review of the code I wrote.&lt;/p&gt;
&lt;p&gt;See the &lt;a href=&#34;https://dmerej.info/blog/pages/contact/&#34;&gt;contact page&lt;/a&gt; for all the possible ways to reach me, and many thanks in advance!&lt;/p&gt;
&lt;h1 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#whats-next&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s a list of features I plan to implement&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Option to delete extraneous files&lt;/li&gt;
&lt;li&gt;Global progress bar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last one is interesting: we need to recursively walk through all the files in the source folder in order to estimate the total size of the transfer, but we want to do that &lt;em&gt;while the transfer is in progress&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That will be an opportunity to play a little bit with Rust concurrency features :)&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: well, I implemented this features using a pipeline of &lt;code&gt;std::sync::mpsc&lt;/code&gt; channels, and it worked great! Here&amp;rsquo;s the &lt;a href=&#34;https://github.com/dmerejkowsky/rusync/commit/01f68335c9593c6cbf99d6d971adf67d2e0ec379&#34;&gt;relevant commit&lt;/a&gt; if you want to take a look.&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Where Software Lives</title>
      <link>https://dmerej.info/blog/post/where-software-lives/</link>
      <pubDate>Thu, 12 Apr 2018 06:05:15 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/where-software-lives/</guid>
      <description>&lt;p&gt;Last night I had a beer with some old friends and colleagues.&lt;/p&gt;
&lt;p&gt;We were discussing a particular library and one of us explained he recently found patches from almost all of us in the git history.&lt;/p&gt;
&lt;p&gt;And then he said (I&amp;rsquo;m paraphrasing a little):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software lives in the minds of the people who wrote it. Code and documentation are nothing but distant echoes of their thoughts at a given time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I could not agree more.&lt;/p&gt;
&lt;p&gt;Code is all but a means to an end, try and remember that.&lt;/p&gt;
&lt;p&gt;Cheers!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 5: Python and cffi</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-5-python-cffi/</link>
      <pubDate>Sat, 07 Apr 2018 17:58:52 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-5-python-cffi/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 5 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/&#34;&gt;Last week&lt;/a&gt; we wrote Python bindings for the chucknorris library using &lt;code&gt;ctypes&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We managed to get some Chuck Norris facts from a Python program.&lt;/p&gt;
&lt;p&gt;On the plus side, we did not have to compile anything. Everything was done directly in Python.&lt;/p&gt;
&lt;p&gt;There were a few issues, though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We had to pass the path to the &lt;code&gt;libchucknorris.so&lt;/code&gt; shared library to &lt;code&gt;ctypes.cdll.LoadLibrary&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We had to duplicate information about parameters types of the C function inside our Python program and mistakes were easy to made.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An other way to wrap C code in Python is to use a &lt;em&gt;C extension&lt;/em&gt;: that is, a Python module written in C. In this case the Python module actually takes the form of a shared library, and is thus loaded by the &lt;code&gt;python&lt;/code&gt; interpreter at runtime.&lt;/p&gt;
&lt;p&gt;There are many ways to create a Python C extension, from directly writing the C code (using the &lt;a href=&#34;https://docs.python.org/3/c-api/index.html&#34;&gt;Python C API&lt;/a&gt;), to generating the C code and then compile it.&lt;/p&gt;
&lt;p&gt;In the past, I&amp;rsquo;ve used tools like &lt;a href=&#34;https://www.boost.org/doc/libs/1_66_0/libs/python/doc/html/index.html&#34;&gt;boost::python&lt;/a&gt; and &lt;a href=&#34;http://www.swig.org/&#34;&gt;swig&lt;/a&gt; for this task.&lt;/p&gt;
&lt;p&gt;I only started using &lt;code&gt;cffi&lt;/code&gt; recently, but I find it easier to use, and, contrary to the above tools, it is compatible with &lt;a href=&#34;https://pypy.org/&#34;&gt;pypy&lt;/a&gt;, which is kind of awesome.&lt;/p&gt;
&lt;h1 id=&#34;first-try-with-cffi&#34;&gt;First try with cffi&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#first-try-with-cffi&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I you browse the &lt;a href=&#34;https://cffi.readthedocs.io/en/latest/index.html&#34;&gt;documentation&lt;/a&gt; you will see that &lt;code&gt;cffi&lt;/code&gt; can be used in several &lt;em&gt;modes&lt;/em&gt;. There is a &lt;em&gt;ABI mode&lt;/em&gt; and an &lt;em&gt;API mode&lt;/em&gt;. The ABI mode resembles the technique we used with &lt;code&gt;ctypes&lt;/code&gt;,  because it involves loading &lt;code&gt;chucknorris&lt;/code&gt; as a shared library.&lt;/p&gt;
&lt;p&gt;We are going to use the &lt;em&gt;API&lt;/em&gt; mode instead, where all the code is generated &lt;em&gt;using the chucknorris.h header&lt;/em&gt;, which minimizes the chance of mistakes.&lt;/p&gt;
&lt;p&gt;This means we can go back to building &lt;code&gt;chucknorris&lt;/code&gt; as a static library. That way we won&amp;rsquo;t have to care about the location of the library, and the  chucknorris code will be used at compile time.(Sorry for the little detour).&lt;/p&gt;
&lt;p&gt;All we have to do is re-run cmake and ninja:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd cpp/ChuckNorris/build/default
$ cmake -DBUILD_SHARED_LIBS=OFF ../..
$ ninja
[1/7] Building C object CMakeFiles/c_demo.dir/src/main.c.o
[2/7] Building CXX object CMakeFiles/chucknorris.dir/src/c_wrapper.cpp.o
[3/7] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[4/7] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[5/7] Linking CXX static library lib/libchucknorris.a
[6/7] Linking CXX executable bin/c_demo
[7/7] Linking CXX executable bin/cpp_demo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, let&amp;rsquo;s write a Python build script for our C extension using the cffi builder:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;build_chucknorris.py&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;cffi&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; FFI
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffibuilder = FFI()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffibuilder.set_source(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;_chucknorris&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    #include &amp;lt;chucknorris.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffibuilder.cdef(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;typedef struct chuck_norris chuck_norris_t;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;chuck_norris_t* chuck_norris_init(void);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;const char* chuck_norris_get_fact(chuck_norris_t*);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;void chuck_norris_deinit(chuck_norris_t*);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;We instantiate a FFI object we call &lt;code&gt;ffibuilder&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;ffibuilder.set_source()&lt;/code&gt; we give the builder the name of the C extension: &lt;code&gt;_chucknorris&lt;/code&gt;. It&amp;rsquo;s common for C extension names to be prefixed with an underscore.&lt;/li&gt;
&lt;li&gt;We also give the FFI builder the C code it needs to compile the code it generates. (Here we only need to include the &lt;code&gt;&amp;lt;chucknorris.h&amp;gt;&lt;/code&gt; header, but in a real project you may add things like macros or additional helper code).&lt;/li&gt;
&lt;li&gt;Finally we list the functions and types we want exposed in our C extension as C declarations &amp;ndash; directly copy/pasted from the &lt;code&gt;chucknorris.h&lt;/code&gt; header &amp;ndash; and pass them as a string to &lt;code&gt;ffibuilder.cdef()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;keeping-things-dry&#34;&gt;Keeping things DRY&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#keeping-things-dry&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;But wait a minute!&amp;rdquo;, &lt;span style=&#34;font-style:normal&#34;&gt;I hear you say&lt;/span&gt;. &amp;ldquo;You said cffi was better than ctypes because we did not have to duplicate information about types, but now you are telling us we still need to copy/paste C declarations inside the call to .cdef()! What gives?&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, it&amp;rsquo;s true we usually try to keep things &lt;em&gt;DRY&lt;/em&gt; when we write code, (DRY meaning &amp;ldquo;don&amp;rsquo;t repeat yourself&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;However, when using cffi it does not matter that much. Not following DRY is only dangerous when the duplicated code &lt;em&gt;does not change at the same time&lt;/em&gt; and gets out of sync.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say you break the API of your library (for instance by changing the number of arguments of a C function). If you don&amp;rsquo;t reflect the change in &lt;code&gt;ffibuilder.def()&lt;/code&gt;, you will get a nice compilation error, instead of a crash or segfault like we experienced with &lt;code&gt;ctypes&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;adding-a-setuppy&#34;&gt;Adding a setup.py&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#adding-a-setuppy&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;With that out of the way, let&amp;rsquo;s add a &lt;code&gt;setup.py&lt;/code&gt; file we can use while developing our bindings, install our code, and re-distribute to others:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;setup.py&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;setuptools&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; setup, find_packages
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setup(name=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;chucknorris&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      version=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      description=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;chucknorris python bindings&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      author=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Dimitri Merejkowsky&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      py_modules=[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;chucknorris&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      setup_requires=[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;cffi&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      cffi_modules=[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build_chucknorris.py:ffibuilder&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      install_requires=[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;cffi&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s what the parameters do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;py_modules&lt;/code&gt;: the list of Python modules to install. We only got one, called &lt;code&gt;chucknorris&lt;/code&gt;, that will use the &lt;code&gt;_chucknorris&lt;/code&gt; C extension and expose a more &amp;ldquo;Pythonic&amp;rdquo; API.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setup_requires&lt;/code&gt;: what the &lt;code&gt;setup.py&lt;/code&gt; script needs in order to build the extension.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cffi_modules&lt;/code&gt;: the list of Python objects to be called when building the extension. Here it&amp;rsquo;s the &lt;code&gt;ffibuilder&lt;/code&gt; object defined in the &lt;code&gt;build_chucknorris.py&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;install_requires&lt;/code&gt;: the list of the dependencies of our module &lt;em&gt;once it has been built and installed&lt;/em&gt;. We &lt;em&gt;also&lt;/em&gt; need &lt;code&gt;cffi&lt;/code&gt; at runtime, not just for compiling the extension.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, we can write the implementation of the chucknorris Python module:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;chucknorris.py:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;_chucknorris&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; lib, ffi
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChuckNorris&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self._ck = lib.chuck_norris_init()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_fact&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        c_fact = lib.chuck_norris_get_fact(self._ck)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fact_as_bytes = ffi.string(c_fact)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; fact_as_bytes.decode(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __del__(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lib.chuck_norris_deinit(self.c_ck)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chuck_norris = ChuckNorris()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(chuck_norris.get_fact())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; __name__ == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    main()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;We start by importing code from the &lt;code&gt;_chucknorris&lt;/code&gt; C extension. &lt;code&gt;lib&lt;/code&gt; contains what has been wrapped &amp;ndash; declared with &lt;code&gt;ffibuilder.cdef()&lt;/code&gt; &amp;ndash; , and &lt;code&gt;ffi&lt;/code&gt; contains various cffi helpers.&lt;/li&gt;
&lt;li&gt;We hide the &lt;code&gt;lib.chuck_norris_init()&lt;/code&gt; and &lt;code&gt;lib.chuck_norris_deinit()&lt;/code&gt; under the &lt;code&gt;__init__&lt;/code&gt; and &lt;code&gt;__del__&lt;/code&gt; methods. (Exactly what we did when going from the C++ constructor and destructors to the C functions, but the other way around)&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;get_fact()&lt;/code&gt; method, we call &lt;code&gt;lib.chuck_norris_get_fact()&lt;/code&gt;. &lt;code&gt;chuck_norris_get_fact()&lt;/code&gt; returns a &amp;ldquo;C string&amp;rdquo;, which is just a &lt;code&gt;char*&lt;/code&gt; array that ends with &lt;code&gt;\0&lt;/code&gt;. We pass it to &lt;code&gt;ffi.string()&lt;/code&gt; to get a &lt;code&gt;bytes&lt;/code&gt; object, suitable for holding this kind of data. And finally, we convert the list of bytes to a real string using &lt;code&gt;decode()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, when the &lt;code&gt;chucknorris.py&lt;/code&gt; script is called, we use our nice Python class as if no C code ever existed :)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;running-the-builder&#34;&gt;Running the builder&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#running-the-builder&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;After installing the &lt;code&gt;cffi&lt;/code&gt; package, we can finally try and build the code:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python setup.py build_ext
running build_ext
generating ./_chucknorris.c
...
building &amp;#39;_chucknorris&amp;#39; extension
gcc ...
  -fPIC
  ...
  -I/usr/include/python3.6m
  -c _chucknorris.c
  -o ./_chucknorris.o
_chucknorris.c:493:14: fatal error: chucknorris.h: No such file or directory
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What happened?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;python setup.py build_ext&lt;/code&gt; found out how to use our &lt;code&gt;ffibuilder&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;It generated some C code in a &lt;code&gt;_chucknorris.c&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;It started building the &lt;code&gt;_chucknorris&lt;/code&gt; extension using &lt;code&gt;_chucknorris.c&lt;/code&gt; and the code we passed in &lt;code&gt;ffibuilder.set_source()&lt;/code&gt; and &lt;code&gt;ffibuilder.cdef()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ffibuilder.compile()&lt;/code&gt; method knew about our old friend &lt;code&gt;-fPIC&lt;/code&gt;, and about the path to the Python includes (&lt;code&gt;-I/usr/include/python3.6m&lt;/code&gt;), but it could not find the &lt;code&gt;chucknorris.h&lt;/code&gt; header and the compilation failed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;tweaking-the-ffibuilder&#34;&gt;Tweaking the ffibuilder&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#tweaking-the-ffibuilder&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Clearly the &lt;code&gt;ffibuilder&lt;/code&gt; needs to know about the chucknorris library and the chucknorris include path.&lt;/p&gt;
&lt;p&gt;We can pass them directly to the &lt;code&gt;set_source()&lt;/code&gt; method using the &lt;code&gt;extra_objects&lt;/code&gt; and &lt;code&gt;include_dirs&lt;/code&gt; parameters. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;build_chucknorris.py&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpp_path = path.Path(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;../cpp/ChuckNorris&amp;#34;&lt;/span&gt;).abspath()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpp_build_path = cpp_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build/default&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ck_lib_path = cpp_build_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/libchucknorris.a&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ck_include_path = cpp_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffibuilder.set_source(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;_chucknorris&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    #include &amp;lt;chucknorris.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    extra_objects=[ck_lib_path],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    include_dirs=[ck_include_path],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that we use the wonderful &lt;a href=&#34;https://github.com/jaraco/path.py&#34;&gt;path.py&lt;/a&gt; library to handle path manipulations, which we can add to our &lt;code&gt;setup.py&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;setuptools&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; setup
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;setup(name=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;chucknorris&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      version=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;0.1&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      setup_requires=[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;cffi&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;path.py&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;the-missing-symbols&#34;&gt;The missing symbols&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-missing-symbols&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s try to build our extension again:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python setup.py build_ext
running build_ext
generating ./_chucknorris.c
...
building &amp;#39;_chucknorris&amp;#39; extension
gcc ... -fPIC ... -I/usr/include/python3.6m -c _chucknorris.c -o ./_chucknorris.o
gcc ... -shared  ... -o build/lib.linux-x86_64-3.6/_chucknorris.abi3.so
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, this works.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s run &lt;code&gt;python setup.py develop&lt;/code&gt; so that we can import the C extension directly:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python setup.py develop
...
generating cffi module &amp;#39;build/temp.linux-x86_64-3.6/_chucknorris.c&amp;#39;
already up-to-date
...
copying build/lib.linux-x86_64-3.6/_chucknorris.abi3.so -&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that &lt;code&gt;setup.py develop&lt;/code&gt; takes care of building the extension for us, and is even capable to skip compilation entirely when nothing needs to be rebuilt.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s run the &lt;code&gt;chucknorris.py&lt;/code&gt; file:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python chucknorris.py
Traceback (most recent call last):
  File &amp;#34;chucknorris.py&amp;#34;, line 1, in &amp;lt;module&amp;gt;
    from _chucknorris import lib, ffi
ImportError: .../_chucknorris.abi3.so: undefined symbol: _ZNSt8ios_base4InitD1Ev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Damned!&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s the problem with shared libraries. &lt;code&gt;gcc&lt;/code&gt; happily lets you build a shared library even if there are symbols that are not defined anywhere. It just assumes the missing symbols will be provided sometime before loading the library.&lt;/p&gt;
&lt;p&gt;Thus, the only way to make sure a shared library has been properly built is to &lt;em&gt;actually load it from an executable&lt;/em&gt; &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Again we are faced with the task of guessing the library from the symbol name. Since it looks like a mangled C++ symbol, we can using &lt;code&gt;c++filt&lt;/code&gt; to get a more human-readable name:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ c++filt _ZNSt8ios_base4InitD1Ev
std::ios_base::Init::~Init
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here I happen to know this is a symbol that comes from the c++ &lt;em&gt;runtime library&lt;/em&gt;, the library that contains things like the implementation of &lt;code&gt;std::string&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can solve the problem by passing the name of the &lt;code&gt;c++&lt;/code&gt; library directly as a &lt;code&gt;libraries&lt;/code&gt; parameter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffibuilder.set_source(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;_chucknorris&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    #include &amp;lt;chucknorris.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    extra_objects=[ck_lib_path],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    include_dirs=[ck_include_path],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    libraries=[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;stdc++&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note: we could also have set the &lt;code&gt;language&lt;/code&gt; parameter to &lt;code&gt;c++&lt;/code&gt;, and invoke the C++ linker when linking &lt;code&gt;_chucknorris.so&lt;/code&gt;, because the C++ linker knows where the c++ runtime library is. &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try again:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python setup.py develop
$ python chucknorris.py
ImportError: .../_chucknorris.abi3.so: undefined symbol: sqlite3_close
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This one is easier: &lt;code&gt;chucknorris&lt;/code&gt; depends on &lt;code&gt;libsqlite3&lt;/code&gt;, so we have to link with &lt;code&gt;sqlite3&lt;/code&gt; too.&lt;/p&gt;
&lt;p&gt;In the CMakeLists.txt we wrote back in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-2-sqlite-conan/&#34;&gt;part 2&lt;/a&gt;, when we were building the &lt;code&gt;cpp_demo&lt;/code&gt; executable, we just called &lt;code&gt;target_link_libraries(cpp_demo chucknorris)&lt;/code&gt;. CMake knew about the dependency from the &lt;code&gt;chucknorris&lt;/code&gt; target to the sqlite3 library and everything worked fine.&lt;/p&gt;
&lt;p&gt;But we&amp;rsquo;re not using the CMake / conan build system here, we are using the Python build system. How can we make them cooperate?&lt;/p&gt;
&lt;h1 id=&#34;the-json-generator&#34;&gt;The json generator&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-json-generator&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Since conan 1.2.0 there is a generator called &lt;code&gt;json&lt;/code&gt; &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; we can use to get machine-readable information about dependencies.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how we can use this json file inside our ffibuilder.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s add &lt;code&gt;json&lt;/code&gt; to the list of conan generators:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;conanfile.txt&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[requires]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;sqlite3/3.21.0@dmerej/test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[generators]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;cmake&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, let&amp;rsquo;s re-run &lt;code&gt;conan install&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd cpp/python/build/default
$ conan install ../..
...
PROJECT: Installing /home/dmerej/src/chucknorris/cpp/ChuckNorris/conanfile.txt
...
sqlite3/3.21.0@dmerej/test: Already installed!
PROJECT: Generator cmake created conanbuildinfo.cmake
PROJECT: Generator json created conanbuildinfo.json
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This generates a &lt;code&gt;conanbuildinfo.json&lt;/code&gt; file looking like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;build/default/conanbuildinfo.json&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;3.21.0&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;sqlite3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;&amp;#34;libs&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;sqlite3&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;pthread&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;dl&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;&amp;#34;include_paths&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/.../.conan/data/sqlite3/.../&amp;lt;id&amp;gt;/include&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;&amp;#34;lib_paths&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/.../.conan/data/sqlite3/.../&amp;lt;id&amp;gt;/lib&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can parse the json file and pass the libraries and include paths to the &lt;code&gt;ffibuilder.set_source()&lt;/code&gt; function:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;build_chucknorris.py&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpp_path = path.Path(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;../cpp/ChuckNorris&amp;#34;&lt;/span&gt;).abspath()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cpp_build_path = cpp_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build/default&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;extra_objects = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;libchucknorris_path = cpp_build_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib/libchucknorris.a&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;extra_objects.append(libchucknorris_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_dirs = []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;include_dirs.append(cpp_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;libraries = [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;stdc++&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;conan_info = json.loads(cpp_build_path.joinpath(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;conanbuildinfo.json&amp;#34;&lt;/span&gt;).text())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; dep &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; conan_info[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; lib_name &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; dep[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;libs&amp;#34;&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lib_filename = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;.a&amp;#34;&lt;/span&gt; % lib_name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; lib_path &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; dep[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;lib_paths&amp;#34;&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            candidate = path.Path(lib_path).joinpath(lib_filename)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; candidate.exists():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                extra_objects.append(candidate)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                libraries.append(lib_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; include_path &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; dep[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;include_paths&amp;#34;&lt;/span&gt;]:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        include_dirs.append(include_path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ffibuilder.set_source(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;_chucknorris&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    #include &amp;lt;chucknorris.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    extra_objects=extra_objects,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    include_dirs=include_dirs,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    libraries=libraries,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now everything works as expected:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python3 setup.py clean develop
$ python chucknorris.py
There are no weapons of mass destruction in Iraq, Chuck Norris lives in Oklahoma.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can even build a pre-compiled wheel that other people can use it without need to compile the chucknorris project themselves:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;On the developer machine:&lt;/em&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python setup.py bdist_wheel
...
running build_ext
...
building &amp;#39;_chucknorris&amp;#39; extension
...
creating &amp;#39;dist/chucknorris-0.1-cp36-cp36m-linux_x86_64.whl&amp;#39; and adding &amp;#39;.&amp;#39; to it
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;em&gt;On an other machine&lt;/em&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ pip install chucknorris-0.1-cp36-cp36m-linux_x86_64.whl
$ python -c &amp;#39;import chucknorris; chucknorris.main()&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For this to work, the other user will need to be on Linux, have a compatible C++ library and the same version of Python, but as far as distribution of binaries on Linux usually go, isn&amp;rsquo;t this nice?&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s an entire blog post to be written about distribution of pre-compiled Python binary modules, but enough about Python for now :)&lt;/p&gt;
&lt;p&gt;See you next time, where we&amp;rsquo;ll use everything we learned there and start &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-6-android-cross-compilation/&#34;&gt;porting Chuck Norris to Android&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&lt;code&gt;ffibuilder.set_source()&lt;/code&gt; uses the same API as the &lt;a href=&#34;https://docs.python.org/3.6/distutils/apiref.html#distutils.core.Extension&#34;&gt;distutils Extension class&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;This also means you should really have at least one executable to test every shared library you write, but you already knew that, right?&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Not sure what the best move is here. If you have an opinion on it, please let me know. PS: I know we could also use static linking, but I&amp;rsquo;m saving that for the part where we build ChuckNorris on Android.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Disclaimer: the json generator feature was added by &lt;a href=&#34;https://github.com/conan-io/conan/pull/2515&#34;&gt;yours truly&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 4: Python and ctypes</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/</link>
      <pubDate>Sat, 31 Mar 2018 12:44:43 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 4 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;static-and-shared-libraries&#34;&gt;Static and shared libraries&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#static-and-shared-libraries&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;C and C++ libraries come in two forms: static and shared.&lt;/p&gt;
&lt;p&gt;In both cases, a library is collection of names (the symbols) and executable code. The difference between static and shared libraries is how those are used, for instance by an executable.&lt;/p&gt;
&lt;p&gt;The code from a static library is &lt;strong&gt;directly integrated&lt;/strong&gt; into the program: the compiler will take copies of the code the program uses from the static library and make it part of the program.&lt;/p&gt;
&lt;p&gt;On the other hand, the code in a shared library is only &lt;strong&gt;referenced by&lt;/strong&gt; the program. When the program is launched, the operating system will try and find the code to run in the shared library file.&lt;/p&gt;
&lt;p&gt;We says the code in the static library is used &lt;em&gt;at compile time&lt;/em&gt; whereas the code of a shared library is used &lt;em&gt;at runtime&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For this reason, static libraries are also called &lt;em&gt;archive libraries&lt;/em&gt;, and shared library are also called &lt;em&gt;dynamic libraries&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Static and shared libraries usually have different extensions depending on the platform:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;platform&lt;/th&gt;
&lt;th&gt;static&lt;/th&gt;
&lt;th&gt;shared&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;.a&lt;/td&gt;
&lt;td&gt;.so&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;.a&lt;/td&gt;
&lt;td&gt;.dylib&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;.lib&lt;/td&gt;
&lt;td&gt;.dll &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So, which type of library do we need to write bindings in Python ?&lt;/p&gt;
&lt;div class=&#34;note&#34;&gt;
  From now on, everything takes place on a &lt;strong&gt;Linux&lt;/strong&gt; machine. There are some differences when using macOS or Windows, but for the sake of simplicity I will only deal with one platform here.
We will also use &lt;strong&gt;Python3&lt;/strong&gt; only. Again, in Python2 things are a little different, but let&amp;rsquo;s keep things simple.
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;p&gt;Since we are using Python as a &lt;em&gt;program&lt;/em&gt; (the &lt;code&gt;/usr/bin/python3&lt;/code&gt; binary), it&amp;rsquo;s obviously too late to do anything at compile time. So let&amp;rsquo;s build a shared library and see what we can do at runtime, shall we?&lt;/p&gt;
&lt;h1 id=&#34;building-the-shared-library&#34;&gt;Building the shared library&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#building-the-shared-library&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When we described the chucknorris library in our CMakeList.txt earlier, we did not specify its type.&lt;/p&gt;
&lt;p&gt;The type of the library used in this case is controlled by a variable called &lt;code&gt;BUILD_SHARED_LIBS&lt;/code&gt; which is &lt;code&gt;OFF&lt;/code&gt; by default. So, let&amp;rsquo;s re-run CMake, setting this variable to &lt;code&gt;ON&lt;/code&gt; instead.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ cmake -GNinja -DBUILD_SHARED_LIBS=ON ../..
$ ninja
...
-- Library sqlite3 found /.conan/data/sqlite3/3.21.0/bincrafters/...libsqlite3.a
...
[1/7] Building C object CMakeFiles/c_demo.dir/src/main.c.o
[2/7] Building CXX object CMakeFiles/chucknorris.dir/src/c_wrapper.cpp.o
[3/7] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[4/7] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[5/7] Linking CXX shared library lib/libchucknorris.so
FAILED: lib/libchucknorris.so
: &amp;amp;&amp;amp; /bin/c++ ...
  -o lib/libchucknorris.so
  ChuckNorris.cpp.o
  c_wrapper.cpp.o
  ...
  libsqlite3.a
  ..
/bin/ld: libsqlite3.a(sqlite3.o): relocation R_X86_64_PC32
against symbol `sqlite3_version` can not be used when making a shared object;
recompile with -fPIC
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The link fails.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s going on here is that we are trying to incorporate a static library (&lt;code&gt;libsqlite3.a&lt;/code&gt;) inside a shared one. Most of the time this works fine, but not on Linux.&lt;/p&gt;
&lt;p&gt;The compiler tells us what needs to be done: we have to recompile &lt;code&gt;libsqlite3.a&lt;/code&gt; with &lt;code&gt;-fPIC&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what &lt;code&gt;man gcc&lt;/code&gt; has to say about &lt;code&gt;fpic&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;-fpic
  Generate position-independent code (PIC) suitable for use in a shared library.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Fair enough, let&amp;rsquo;s try to rebuild &lt;code&gt;sqlite3&lt;/code&gt; by generating position-independent code.&lt;/p&gt;
&lt;h1 id=&#34;patching-a-conan-recipe&#34;&gt;Patching a conan recipe&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#patching-a-conan-recipe&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The first step is to see if we can rebuild sqlite3 ourselves.&lt;/p&gt;
&lt;p&gt;We will be using a different user name and channel. (&lt;em&gt;@dmerej/test&lt;/em&gt; instead of &lt;em&gt;@bincrafters/stable&lt;/em&gt;). As we explained earlier, conan is decentralized, so copying and modifying other people&amp;rsquo;s recipes in order to satisfy your requirements is possible and even encouraged.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s fetch the recipe from the remote:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan copy sqlite3/3.21.0@bincrafters/stable dmerej/test
Downloading conan_sources.tgz
[==================================================] 706B/706B
Copied sqlite3/3.21.0@bincrafters/stable to sqlite3/3.21.0@dmerej/test
Copied sources sqlite3/3.21.0@bincrafters/stable to sqlite3/3.21.0@dmerej/test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here conan looked for the recipe in the remote and created a copy with a different name, but still inside the conan cache.&lt;/p&gt;
&lt;p&gt;Then we copy the sources from the cache and put them in a &lt;code&gt;conan/sqlite3&lt;/code&gt; folder next to the C++ code:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd ChuckNorris/cpp
$ mkdir -p conan/sqlite3
$ cd conan/sqlite3
$ cp -rv ~/.conan/data/sqlite3/3.21.0/bincrafters/stable/export/* .
&amp;#39;../conanfile.py&amp;#39; -&amp;gt; &amp;#39;./conanfile.py&amp;#39;
&amp;#39;../conanmanifest.txt&amp;#39; -&amp;gt; &amp;#39;./conanmanifest.txt&amp;#39;
&amp;#39;../LICENSE.md&amp;#39; -&amp;gt; &amp;#39;./LICENSE.md&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s try to build the package ourselves:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan create . dmerej/test
sqlite3/3.21.0@dmerej/test: Exporting package recipe
sqlite3/3.21.0@dmerej/test: A new conanfile.py version was exported
...
sqlite3/3.21.0@dmerej/test: Installing package
..
sqlite3/3.21.0@dmerej/test: Attempting download of sources from:
  https://www.sqlite.org/2017/sqlite-amalgamation-3210000.zip
...
sqlite3/3.21.0@dmerej/test: Calling build()
CMake Error: The source directory &amp;#34;...&amp;#34; does not appear to contain CMakeLists.txt.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Turns out we need to also copy some files from the &lt;code&gt;export_source&lt;/code&gt; folder:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cp -rv ~/.conan/data/sqlite3/3.21.0/bincrafters/stable/export_source/* .
&amp;#39;../CMakeLists.txt -&amp;gt; &amp;#39;./CMakeLists.txt&amp;#39;
&amp;#39;../FindSQLite3.cmake&amp;#39; -&amp;gt; &amp;#39;./FindSQLite3.cmake&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now we can build:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan create . dmerej/test
sqlite3/3.21.0@dmerej/test: Exporting package recipe
sqlite3/3.21.0@dmerej/test: A new conanfile.py version was exported
...
sqlite3/3.21.0@dmerej/test: Installing package
..
sqlite3/3.21.0@dmerej/test: Attempting download of sources from:
  https://www.sqlite.org/2017/sqlite-amalgamation-3210000.zip
...
sqlite3/3.21.0@dmerej/test: Calling build()
...
[1/2] Building C object CMakeFiles/sqlite3.dir/sources/sqlite3.o
[2/2] Linking C static library lib/libsqlite3.a
...
sqlite3/3.21.0@dmerej/test: Package &amp;#39;6ae331b7...&amp;#39; built
...
sqlite3/3.21.0@dmerej/test: Calling package()
sqlite3/3.21.0@dmerej/test package(): Copied 1 &amp;#39;.cmake&amp;#39; files: FindSQLite3.cmake
sqlite3/3.21.0@dmerej/test package(): Copied 2 &amp;#39;.h&amp;#39; files: sqlite3.h, sqlite3ext.h
sqlite3/3.21.0@dmerej/test package(): Copied 1 &amp;#39;.a&amp;#39; files: libsqlite3.a
...
sqlite3/3.21.0@dmerej/test: Package &amp;#39;6ae331b7...&amp;#39; created
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s sum up what happened:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conan fetched the sources from &lt;code&gt;sqlite.org&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It called &lt;code&gt;CMake&lt;/code&gt; using the &lt;code&gt;CMakeLists.txt&lt;/code&gt; we copied from &lt;code&gt;export_source&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It built the CMake project using a function named &lt;code&gt;build()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It copied some files using a function named &lt;code&gt;package()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is roughly what we did earlier when we built sqlite by hand.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a closer look at the conan source files:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;CMakeList.txt&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;project&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;cmake_wrapper&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;include&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;conanbuildinfo.cmake&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;conan_basic_setup&lt;/span&gt;()&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;add_library&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;sqlite3&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;sources/sqlite3.c&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;conanfile.py&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ConanSqlite3&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;sqlite3&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    version = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;3.21.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    settings = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiler&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build_type&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options = {&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;source&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        base_url = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;https://www.sqlite.org/&amp;#34;&lt;/span&gt; + self.year
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        download_url = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{0}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{1}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;{2}&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;.format(base_url, archive_name, archive_ext)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tools.get(download_url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;build&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake = CMake(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake.configure()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake.build()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;package&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.copy(...)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The conan recipe is just a Python class that derives from the &lt;code&gt;ConanFile&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;It contains the &lt;code&gt;source()&lt;/code&gt;, &lt;code&gt;build()&lt;/code&gt; and &lt;code&gt;package()&lt;/code&gt; methods used to fetch the sources, build the package, and copy the relevant files we saw mentioned in the previous console output.&lt;/p&gt;
&lt;p&gt;It uses a &lt;code&gt;CMake&lt;/code&gt; class that knows how to run &lt;code&gt;cmake&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, the class contains a few attributes. &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt; are self-explanatory, but we have to talk about the &lt;code&gt;settings&lt;/code&gt; and &lt;code&gt;options&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In both cases, settings and options are variables the consumers of the package can set. The settings cannot have default values, and if a setting changes, a different package must be produced. This is why the compiler (think &lt;code&gt;gcc&lt;/code&gt; versus &lt;code&gt;Visual Studio&lt;/code&gt;) is a setting. Settings are set globally, usually inside a profile, and apply to all the recipes. Options are different: they can have default values, they can be set package per package, and they have a pre-defined list of possible values.&lt;/p&gt;
&lt;p&gt;We can see the &lt;code&gt;conanfile.py&lt;/code&gt; already defines a &lt;code&gt;shared&lt;/code&gt; option that can be true or false. We do not really want a shared &lt;code&gt;sqlite3&lt;/code&gt; library, we want a static &lt;code&gt;sqlite3&lt;/code&gt; library but built with position independent code.&lt;/p&gt;
&lt;p&gt;There are several ways to do this. One of them is to introduce a new option called &lt;code&gt;pic&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;CMake knows how to convert the abstract concept of &amp;ldquo;position independent code&amp;rdquo; into concrete compiler flags such as &lt;code&gt;-fPIC&lt;/code&gt; for gcc, so we just have to set the correct CMake variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ConanSqlite3&lt;/span&gt;(ConanFile):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    settings = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;compiler&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build_type&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    options = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;shared&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;pic&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;build&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cmake = CMake(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.options.shared:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            cmake.definitions[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;BUILD_SHARED_LIBS&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; self.options.pic:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            cmake.definitions[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;CMAKE_POSITION_INDEPENDENT_CODE&amp;#34;&lt;/span&gt;] = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;ON&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So now we can re-create the &lt;code&gt;sqlite3&lt;/code&gt; package:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ conan create --option &amp;#39;pic=True&amp;#39; . dmerej/test
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, we can change the &lt;code&gt;conanfile.txt&lt;/code&gt; in &lt;code&gt;cpp/ChuckNorris&lt;/code&gt; to reference our newly built package:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;conanfile.txt&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[requires]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;sqlite3/3.21.0@dmerej/test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;using-the-chucknorris-shared-library&#34;&gt;Using the chucknorris shared library&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-the-chucknorris-shared-library&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s re-run &lt;code&gt;conan install&lt;/code&gt;, using the &lt;code&gt;--option&lt;/code&gt; command line flag again, and see if we can manage to build chucknorris the way we want.&lt;/p&gt;
&lt;p&gt;Note that we prefix the &lt;code&gt;pic=True&lt;/code&gt; option by the name of the package we want to apply the option on. If we did not do that, &lt;code&gt;conan&lt;/code&gt; would have tried to set the option on &lt;em&gt;every&lt;/em&gt; package.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ conan install ../.. --option &amp;#39;sqlite3:pic=True&amp;#39;
$ cmake -GNinja -DBUILD_SHARED_LIBS=ON ../..
$ ninja
[1/7] Building C object CMakeFiles/c_demo.dir/src/main.c.o
[2/7] Building CXX object CMakeFiles/chucknorris.dir/src/c_wrapper.cpp.o
[3/7] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[4/7] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[5/7] Linking CXX shared library lib/libchucknorris.so
[6/7] Linking C executable bin/c_demo
[7/7] Linking CXX executable bin/cpp_demo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Success!&lt;/p&gt;
&lt;p&gt;Side note: specifying the option about &lt;code&gt;sqlite3&lt;/code&gt; each time we call &lt;code&gt;conan&lt;/code&gt; is a bit tedious, but we can just specify the option directly in the &lt;code&gt;conanfile.txt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[requires]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;sqlite3/3.21.0@dmerej/test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[options]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;sqlite3:pic&lt;/span&gt; = &lt;span style=&#34;color:#ed9d13&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Anyway, we said earlier that it was the operating system that took care of loading code from the shared library at runtime. On Linux, this is done by a special shared library called &lt;code&gt;ld-linux.so&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can thus check that the &lt;code&gt;libchucknorris.so&lt;/code&gt; file does get loaded when we run the &lt;code&gt;cpp_demo&lt;/code&gt; executable, by asking &lt;code&gt;ld.so&lt;/code&gt; to output debug information about the files it loads &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ export LD_TRACE_LOADED_OBJECTS=1
$ ./bin/cpp_demo
./bin/cpp_demo
	linux-vdso.so.1 (0x00007f...)
	libchucknorris.so =&amp;gt; .../build/default/lib/libchucknorris.so (0x00007f...)
    ...
	libpthread.so.0 =&amp;gt; /usr/lib/libpthread.so.0 (0x00007f...)
	libdl.so.2 =&amp;gt; /usr/lib/libdl.so.2 (0x00007f...)
    ...
Chuck Norris knows Victoria&amp;#39;s secret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Our friends &lt;code&gt;libpthread.so&lt;/code&gt; and &lt;code&gt;libdl.so&lt;/code&gt; we had to take care of when we linked with &lt;code&gt;sqlite3&lt;/code&gt; by hand are involved, and we can see the full path of the ChuckNorris lib inside our build folder.&lt;/p&gt;
&lt;h1 id=&#34;using-ctypes&#34;&gt;Using ctypes&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#using-ctypes&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The Python standard library contains a module called &lt;code&gt;ctypes&lt;/code&gt; that allows to do what &lt;code&gt;ld.so&lt;/code&gt; does, but using Python code.&lt;/p&gt;
&lt;p&gt;The documentation says we can use &lt;code&gt;ctypes.cdll.LoadLibrary&lt;/code&gt; to get a &amp;ldquo;handle&amp;rdquo; from the &lt;code&gt;.so&lt;/code&gt;, and then use the symbols in the shared library simply by calling methods with the right names on the handle.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;handle = ctypes.cdll.LoadLibrary(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build/default/lib/libchucknorris.so&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ck = handle.chuck_norris_init()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fact = handle.chuck_norris_get_fact(ck)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(fact)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python ck.py
zsh: segmentation fault (core dumped)  python ck.py
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Whoops :/&lt;/p&gt;
&lt;p&gt;Actually for this to work we have to specify the types of the parameters and return values for every method we call, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;handle = ctypes.cdll.LoadLibrary(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;build/default/lib/libchucknorris.so&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;handle.chuck_norris_init.restype = ctypes.c_void_p
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;handle.chuck_norris_get_fact.restype = ctypes.c_char_p
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;handle.chuck_norris_get_fact.argtypes = [ctypes.c_void_p]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ck = handle.chuck_norris_init()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fact = handle.chuck_norris_get_fact(ck)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(fact)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python ck.py
b&amp;#39;When Chuck Norris enters a rodeo the bull has to try and last 8 seconds.&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Almost there: we still have get rid of the &lt;code&gt;b&#39;&lt;/code&gt; prefix.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ctypes&lt;/code&gt; can&amp;rsquo;t really assume a &lt;code&gt;char *&lt;/code&gt; in C code contains text, so the &lt;code&gt;c_char_p&lt;/code&gt; type has been translated to a &lt;code&gt;bytes&lt;/code&gt; object, suitable for representing binary data.&lt;/p&gt;
&lt;p&gt;Assuming we were careful and only inserted valid UTF-8 encoded text in our sqlite3 database, we can call &lt;code&gt;.decode(UTF-8)&lt;/code&gt; in our Python code, though:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fact_as_bytes = handle.chuck_norris_get_fact(ck)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fact_text = fact_as_bytes.decode(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;print&lt;/span&gt;(fact_text)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python ck.py
When Chuck Norris enters a rodeo the bull has to try and last 8 seconds.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And we&amp;rsquo;re done.&lt;/p&gt;
&lt;p&gt;This is all well and good, but there&amp;rsquo;s a more robust method to write our Python bindings. You can read more about it in &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-5-python-cffi/&#34;&gt;part 5&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Actually, on Windows when you want to link with a shared library, you use both a &lt;code&gt;.lib&lt;/code&gt; when linking and a &lt;code&gt;.dll&lt;/code&gt; at runtime. It&amp;rsquo;s confusing, I know.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;This is the technique used by &lt;code&gt;ldd&lt;/code&gt;, by the way.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 3: A C wrapper</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-3-a-c-wrapper/</link>
      <pubDate>Sun, 25 Mar 2018 16:50:30 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-3-a-c-wrapper/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 3 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;introduction-when-languages-talk-together&#34;&gt;Introduction: when languages talk together&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction-when-languages-talk-together&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;C is kind like the lingua franca of programming languages. Many languages implementations are themselves &lt;em&gt;written&lt;/em&gt; in C, and almost all of them know how to call C code. Often this is called using a &lt;em&gt;Foreign Function Interface&lt;/em&gt;, or FFI for short.&lt;/p&gt;
&lt;p&gt;Our goal with the Chuck Norris project is to use our library in a lot of various situations (such as in an iOS or Android application), so why did we not write the chucknorris library in C?&lt;/p&gt;
&lt;p&gt;Well, C++ has many advantages compared to C:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Strings are easier to handle&lt;/li&gt;
&lt;li&gt;Memory management is simpler&lt;/li&gt;
&lt;li&gt;You can use nice tools such as classes and templates&lt;/li&gt;
&lt;li&gt;&amp;hellip; and more!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C and C++ are not so far apart: For instance, calling C from C++ works out of he box. &lt;code&gt;sqlite3&lt;/code&gt; is written in C, and in our code we just had to include &lt;code&gt;&amp;lt;sqlite3.h&amp;gt;&lt;/code&gt; and everything &amp;ldquo;just worked&amp;rdquo;. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But things get more interesting when we try to go the other way around.&lt;/p&gt;
&lt;h1 id=&#34;calling-c-code-from-c&#34;&gt;Calling C++ code from C&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#calling-c-code-from-c&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;In our library we expose a class, but C does not know about classes. So we are going to  declare a C API, and then implement the C API using C++ code.&lt;/p&gt;
&lt;p&gt;We can do this because C++ is a &amp;ldquo;superset&amp;rdquo; of C.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a few details to get right though, so let&amp;rsquo;s do this step by step.&lt;/p&gt;
&lt;h2 id=&#34;declaring-a-c-api&#34;&gt;Declaring a C API&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#declaring-a-c-api&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;C does not know about classes, so we cannot use the &lt;code&gt;ChuckNorris&lt;/code&gt; symbol anywhere.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what we can do:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;include/chucknorris.h:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; chuck_norris &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;chuck_norris_t&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;chuck_norris_t&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;chuck_norris_t&lt;/span&gt;*);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;chuck_norris_t&lt;/span&gt;*);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Each function is prefixed with &lt;code&gt;chuck_norris_&lt;/code&gt; (because there are no namespaces in C)&lt;/li&gt;
&lt;li&gt;We declare a &lt;code&gt;chuck_norris_t&lt;/code&gt; struct type but do not bother to describe what&amp;rsquo;s inside. This works because the other functions will either return or take a parameter of the &lt;code&gt;chuck_norris_t&lt;/code&gt; &lt;strong&gt;pointer&lt;/strong&gt; type, so the compiler does not need to know what&amp;rsquo;s inside the struct. This is known as an &lt;em&gt;opaque pointer&lt;/em&gt;. In the C++ implementation, we&amp;rsquo;ll have to perform casts between the &amp;ldquo;real&amp;rdquo; &lt;code&gt;ChuckNorris*&lt;/code&gt; pointers and the opaque &lt;code&gt;chuck_norris*&lt;/code&gt; ones.&lt;/li&gt;
&lt;li&gt;Instead of letting the compiler handle creation and destruction of the C++ class, we have explicit functions: &lt;code&gt;chuck_norris_init()&lt;/code&gt; and &lt;code&gt;chuck_norris_deinit()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Instead of a &lt;code&gt;getFact()&lt;/code&gt; method inside a class, we have a &lt;code&gt;chuck_norris_get_fact()&lt;/code&gt; function that takes opaque &lt;code&gt;chuck_norris&lt;/code&gt; pointer as first parameter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;implementing-the-c-api&#34;&gt;Implementing the C API&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#implementing-the-c-api&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s what our first attempt looks like:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;src/c_wrapper.cpp:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;cstring&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;chucknorris.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;ChuckNorris.hpp&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chuck_norris_t* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; ck = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;new&lt;/span&gt; ChuckNorris();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;chuck_norris*&amp;gt;(ck);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(chuck_norris_t* chuck_norris)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; ck = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;ChuckNorris*&amp;gt;(chuck_norris);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std::string fact = ck-&amp;gt;getFact();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* result = fact.c_str();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(chuck_norris_t* chuck_norris)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; ck = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;ChuckNorris*&amp;gt;(chuck_norris);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;delete&lt;/span&gt; ck;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The only cast we can use is &lt;code&gt;reinterpret_cast&lt;/code&gt;, which basically tell the compiler &amp;ldquo;trust us, what&amp;rsquo;s inside the pointer is of the right type!&amp;rdquo;. This means things will go terribly wrong if callers of the C API are not careful, but don&amp;rsquo;t worry, they&amp;rsquo;re used to it :P&lt;/p&gt;
&lt;p&gt;To check it works, let&amp;rsquo;s add an other test executable, written in C this time:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;src/main.c&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;chucknorris.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;chuck_norris_t&lt;/span&gt;* ck = &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* fact = &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(ck);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;, fact);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(ck);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s adapt the CMake code to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add the &lt;code&gt;c_wrapper.cpp&lt;/code&gt; file to the list of the sources of the &lt;code&gt;chucknorris&lt;/code&gt; library.&lt;/li&gt;
&lt;li&gt;Add a &lt;code&gt;c_demo&lt;/code&gt; executable built with from the &lt;code&gt;main.c&lt;/code&gt; file:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  add_library(chucknorris
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    include/ChuckNorris.hpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    include/chucknorris.h
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    src/ChuckNorris.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   src/c_wrapper.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;  )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ add_executable(c_demo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   src/main.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ )
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ target_link_libraries(c_demo chucknorris)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And let&amp;rsquo;s try to compile:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ ninja
[1/7] Building C object CMakeFiles/c_demo.dir/src/main.c.o
[2/7] Building CXX object CMakeFiles/chucknorris.dir/src/c_wrapper.cpp.o
[3/7] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[4/7] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[5/7] Linking CXX static library lib/libchucknorris.a
[6/7] Linking CXX executable bin/c_demo
FAILED: bin/c_demo
: &amp;amp;&amp;amp; /bin/c++ main.c.o -o bin/c_demo lib/libchucknorris.a ...
CMakeFiles/c_demo.dir/src/main.c.o: In function `main&amp;#39;:
main.c:(.text+0x9): undefined reference to `chuck_norris_init&amp;#39;
main.c:(.text+0x19): undefined reference to `chuck_norris_get_fact&amp;#39;
main.c:(.text+0x35): undefined reference to `chuck_norris_deinit&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can see the &lt;code&gt;libchucknorris.a&lt;/code&gt; library was passed to the linker, so why were the symbols not found ?&lt;/p&gt;
&lt;h2 id=&#34;mangled-symbols&#34;&gt;Mangled symbols&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#mangled-symbols&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To understand, let&amp;rsquo;s look at the names of the symbols inside the &lt;code&gt;libchucknorris.a&lt;/code&gt; library using a tool called &lt;code&gt;nm&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ nm --defined-only libchucknorris.a

ChuckNorris.cpp.o:
0000000000000000 V DW.ref.__gxx_personality_v0
...
000000000000020c T _ZN11ChuckNorris7getFactB5cxx11Ev

c_wrapper.o
...
0000000000000000 T _Z17chuck_norris_initv
00000000000000ac T _Z19chuck_norris_deinitP11ChuckNorris
000000000000003c T _Z21chuck_norris_get_factP11ChuckNorris
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hum. The names of the symbols do not match the ones we declared in the headers.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s because they were &lt;em&gt;mangled&lt;/em&gt; by the C++ compiler. I won&amp;rsquo;t detail here the reasons why the symbols have to be mangled in the first place. Let&amp;rsquo;s just say it has to do with stuff like function overloading and things like that.&lt;/p&gt;
&lt;p&gt;We can check that the &lt;code&gt;cpp_demo&lt;/code&gt; binary contains a reference to the weird &lt;code&gt;getFact&lt;/code&gt; symbol:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ nm --defined-only cpp_demo
...
000000000000cefe T _ZN11ChuckNorris7getFactB5cxx11Ev
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can also use the &lt;code&gt;--demangle&lt;/code&gt; option when calling &lt;code&gt;nm&lt;/code&gt; and see the original names:&lt;/p&gt;
&lt;p&gt;(note that the C symbols were mangled too)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ nm --demangle --defined-only libchucknorris.a
...
00000000000001b0 T ChuckNorris::getFact[abi:cxx11]()
...
0000000000000000 T chuck_norris_init()
00000000000000ac T chuck_norris_deinit(ChuckNorris*)
000000000000003c T chuck_norris_get_fact(ChuckNorris*)

$ nm --demangle --defined-only cpp_demo
...
000000000000cefe T ChuckNorris::getFact[abi:cxx11]()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When we compiled &lt;code&gt;c_demo.o&lt;/code&gt;, we used a &lt;em&gt;C&lt;/em&gt; compiler. (CMake saw a &lt;code&gt;.c&lt;/code&gt; extension on the source file, and thus told ninja to build &lt;code&gt;main.c.o&lt;/code&gt; with a C compiler)&lt;/p&gt;
&lt;p&gt;Since the C compiler does &lt;em&gt;not&lt;/em&gt; mangle symbols at all, the final link between &lt;code&gt;c_demo.o&lt;/code&gt; and &lt;code&gt;libchucknorris.a&lt;/code&gt; failed.&lt;/p&gt;
&lt;p&gt;The solution is to tell the C++ compiler to &lt;em&gt;not&lt;/em&gt; mangle the symbols defined in the &lt;code&gt;chucknorris.h&lt;/code&gt; header using the &lt;code&gt;extern&lt;/code&gt; syntax&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extern&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;chuck_norris&lt;/span&gt; chuck_norris_t;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  chuck_norris_t* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(chuck_norris_t*);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(chuck_norris_t*);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But if we do that, we now get a compile failure because the C compiler does not understand the &lt;code&gt;extern&lt;/code&gt; syntax:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ninja
/bin/cc  -o main.c.o -c main.c
In file included from ../../src/main.c:1:0:
chucknorris.h:3:8: error: expected identifier or ‘(’ before string constant
extern &amp;#34;C&amp;#34; {
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Fortunately, the C++ compiler sets a &lt;code&gt;__cplusplus&lt;/code&gt; define for us:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;extern&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;C&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  chuck_norris_t* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;(&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(chuck_norris_t*);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(chuck_norris_t*);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#ifdef __cplusplus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the build passes &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, and we can double-check the names of symbols inside the archive:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ninja
[1/7] Building C object CMakeFiles/c_demo.dir/src/main.c.o
[2/7] Building CXX object CMakeFiles/chucknorris.dir/src/c_wrapper.cpp.o
[3/7] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[4/7] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[5/7] Linking CXX static library lib/libchucknorris.a
[6/7] Linking CXX executable bin/cpp_demo
[7/7] Linking CXX executable bin/c_demo

$ nm --defined-only libchucknorris.a
ChuckNorris.cpp.o:
0000000000000000 V DW.ref.__gxx_personality_v0
...
0000000000000160 T _ZN11ChuckNorrisC1Ev
...
000000000000020c T _ZN11ChuckNorris7getFactB5cxx11Ev

c_wrapper.o
...
0000000000000000 T chuck_norris_init
00000000000000ac T chuck_norris_deinit
000000000000003c T chuck_norris_get_fact
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;the-string-bug&#34;&gt;The string bug&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-string-bug&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hooray, we managed to build our C code! Let&amp;rsquo;s run it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ./bin/c_demo
���rU
 ./bin/c_demo
����BV
./bin/c_demo
`15R�U
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hum. Something is not right.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look again at the &lt;code&gt;chuck_norris_get_fact&lt;/code&gt; implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(chuck_norris_t* chuck_norris)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; ck = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;ChuckNorris*&amp;gt;(chuck_norris);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std::string fact = ck-&amp;gt;getFact();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* result = fact.c_str();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s what&amp;rsquo;s happening:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First we call &lt;code&gt;chuck_norris-&amp;gt;getFact()&lt;/code&gt; and create a local variable named &lt;code&gt;fact&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Then we get a &lt;code&gt;char*&lt;/code&gt; pointer to the contents of the &lt;code&gt;std::string&lt;/code&gt; with &lt;code&gt;c_str()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;We return the &lt;code&gt;char*&lt;/code&gt; pointer&lt;/li&gt;
&lt;li&gt;But then the &lt;code&gt;fact&lt;/code&gt; variable gets out of scope and the contents of the &lt;code&gt;std::string&lt;/code&gt; are freed. Note that this is what &lt;code&gt;std::string&lt;/code&gt;s are &lt;em&gt;designed&lt;/em&gt; to do: they handle memory management for us. We are only having this problem because we are playing with raw C pointers!&lt;/li&gt;
&lt;li&gt;Now our &lt;code&gt;char*&lt;/code&gt; pointer points to uninitialized stuff and we get garbage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution is to call &lt;code&gt;strdup&lt;/code&gt; to get a copy of the contents that we now &lt;em&gt;own&lt;/em&gt; and to free it explicitly later on.&lt;/p&gt;
&lt;p&gt;(Note that the returned pointer is no longer &lt;code&gt;const&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;src/c_wrapper.cpp:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(chuck_norris_t* chuck_norris)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; ck = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;ChuckNorris*&amp;gt;(chuck_norris);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std::string fact = ck-&amp;gt;getFact();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* result = strdup(fact.c_str());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;src/main.c:&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;chuck_norris_t&lt;/span&gt;* ck = &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_init&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;* fact = &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_get_fact&lt;/span&gt;(ck);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt;, fact);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;free&lt;/span&gt;(fact);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#447fcf&#34;&gt;chuck_norris_deinit&lt;/span&gt;(ck);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now the binary works:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ninja
$ ./bin/c_demo
Chuck Norris counted to infinity. Twice.;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&amp;rsquo;s all for today. The C library is the building block we&amp;rsquo;ll use to &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/&#34;&gt;write Python bindings&lt;/a&gt; and phone applications. Stay tuned for the rest of the story!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;That&amp;rsquo;s a lie. There&amp;rsquo;s something special in the &lt;code&gt;sqlite3.h&lt;/code&gt; file to make this work. But we&amp;rsquo;ll talk about that later.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;This little trick of &lt;code&gt;#ifdef __cplusplus&lt;/code&gt; and &lt;code&gt;extern &amp;quot;C&amp;quot;&lt;/code&gt; is used pretty often in the wild, and you do find it in the &lt;code&gt;sqlite3.h&lt;/code&gt; header. I had to lie to preserve the flow of the article, sorry.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 2: SQLite and conan</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-2-sqlite-conan/</link>
      <pubDate>Sun, 18 Mar 2018 14:29:21 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-2-sqlite-conan/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 2 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the previous episode we wrote a simple C++ library that returned a hard-coded Chuck Norris fact.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s now time to put several Chuck Norris facts in a database, and select one at random when asked.&lt;/p&gt;
&lt;p&gt;We are going to use &lt;a href=&#34;https://www.sqlite.org/index.html&#34;&gt;sqlite&lt;/a&gt; for that.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s adapt our class declaration:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;include/ChuckNorris.hpp&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;sqlite3.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChuckNorris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ChuckNorris();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Make sure you cannot copy Chuck Norris
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;    ChuckNorris(ChuckNorris &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt;&amp;amp;) = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;delete&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ChuckNorris(ChuckNorris &amp;amp;&amp;amp;) = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;delete&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ChuckNorris&amp;amp; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;operator&lt;/span&gt;=(ChuckNorris &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt;&amp;amp;) = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;delete&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ChuckNorris&amp;amp; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;operator&lt;/span&gt;=(ChuckNorris &amp;amp;&amp;amp;) = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;delete&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ~ChuckNorris();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std::string getFact();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;private&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sqlite3* _db;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, it&amp;rsquo;s time to adapt the &lt;code&gt;ChuckNorris.cpp&lt;/code&gt; file:&lt;/p&gt;
&lt;p&gt;In the constructor, we open an in-memory database and fill it with lots of facts.&lt;/p&gt;
&lt;p&gt;Then, in the &lt;code&gt;getFact()&lt;/code&gt; method, we run a simple SQL query:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;src/ChuckNorris.cpp&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note: Error handling omitted for brevity.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;sqlite3.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;ChuckNorris.hpp&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ChuckNorris::ChuckNorris()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sqlite3_open(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;:memory:&amp;#34;&lt;/span&gt;, &amp;amp;_db);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; sql = R&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CREATE TABLE &lt;span style=&#34;color:#447fcf&#34;&gt;chucknorris&lt;/span&gt;(id PRIMARY_KEY, fact VARCHAR(&lt;span style=&#34;color:#3677a9&#34;&gt;500&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSERT INTO &lt;span style=&#34;color:#447fcf&#34;&gt;chucknorris&lt;/span&gt; (fact) VALUES
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Chuck Norris can slam a revolving door.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;INSERT INTO &lt;span style=&#34;color:#447fcf&#34;&gt;chucknorris&lt;/span&gt; (fact) VALUES
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Chuck Norris can kill two stones with one bird.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  )&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sqlite3_exec(_db, sql, &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;nullptr&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ChuckNorris::~ChuckNorris()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sqlite3_close(_db);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std::string ChuckNorris::getFact()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// Note: error handling omitted for brevity
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sqlite3_stmt* statement;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; rc;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  rc = sqlite3_prepare_v2(_db,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      R&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;(SELECT fact FROM chucknorris ORDER BY RANDOM() LIMIT 1;)&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      -&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;, &amp;amp;statement, &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; (rc != SQLITE_OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  rc = sqlite3_step(statement);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; (rc != SQLITE_ROW) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; sqlite_row = sqlite3_column_text(statement, &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; row = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;reinterpret_cast&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;char&lt;/span&gt;*&amp;gt;(sqlite_row);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;auto&lt;/span&gt; res = std::string(row);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sqlite3_finalize(statement);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; res;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s try and compile this!&lt;/p&gt;
&lt;h1 id=&#34;third-party-libraries&#34;&gt;Third party libraries&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#third-party-libraries&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Since we are not the authors of the &lt;code&gt;sqlite&lt;/code&gt; library, we say it is a &lt;em&gt;third-party&lt;/em&gt; library. (As opposed to the &lt;code&gt;chucknorris&lt;/code&gt; library we just wrote).&lt;/p&gt;
&lt;p&gt;There are a lot of ways of adding a third-party dependency to a C++ program, from simply adding the sources to the project files, to installing them &amp;ldquo;in the system&amp;rdquo; (using &lt;code&gt;homebrew&lt;/code&gt; on macOS or the package manager of your distribution on Linux).&lt;/p&gt;
&lt;p&gt;In this article we will use a package manager called &lt;a href=&#34;https://conan.io&#34;&gt;conan&lt;/a&gt; that will install the &lt;code&gt;sqlite3&lt;/code&gt; package somewhere in our home directory (called a &lt;em&gt;cache&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;This means we won&amp;rsquo;t need any administrative privileges (as opposed to installing the &lt;code&gt;sqlite3&lt;/code&gt; library in the system), but also that the library will usable from multiple C++ projects (as opposed to adding the sources of &lt;code&gt;sqlite3&lt;/code&gt; inside our source folder).&lt;/p&gt;
&lt;p&gt;Using conan will come in handy when we start cross-compiling things later, but I&amp;rsquo;m getting ahead of myself.&lt;/p&gt;
&lt;h1 id=&#34;adding-the-dependency-by-hand&#34;&gt;Adding the dependency by hand&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#adding-the-dependency-by-hand&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s start by doing the work &amp;ldquo;by hand&amp;rdquo; before we talk about how conan works.&lt;/p&gt;
&lt;h2 id=&#34;building-sqlite3&#34;&gt;Building sqlite3&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#building-sqlite3&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, we go to &lt;a href=&#34;https://www.sqlite.org/download.html&#34;&gt;the download page of the sqlite3 project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We then fetch the &amp;ldquo;almagation&amp;rdquo; archive, and extract it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd $HOME
$ mkdir -p 3rdpart/sqlite
$ cd 3rdpart/sqlite
$ wget https://www.sqlite.org/2018/sqlite-amalgamation-3220000.zip
$ unzip sqlite-amalgamation-3220000.zip
$ cd sqlite-amalgamation-3220000
$ ls
$ shell.c  sqlite3.c  sqlite3.h  sqlite3ext.h
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, we just have a &lt;code&gt;sqlite3.c&lt;/code&gt; to build and a &lt;code&gt;sqlite3.h&lt;/code&gt; header that we can include.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s build a static library:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ gcc -c sqlite3.c -o sqlite3.o
$ ar qf libsqlite3.a sqlite3.o
$ ranlib libsqlite3.a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And, just to clean things up, let&amp;rsquo;s create a &lt;code&gt;lib&lt;/code&gt; and &lt;code&gt;include&lt;/code&gt; folder:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ mkdir include lib
$ mv libsqlite3.a lib/
$ mv sqlite3.h include/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we have to adapt the &lt;code&gt;CMakeLists.txt&lt;/code&gt; in the Chuck Norris sources to use our newly built library.&lt;/p&gt;
&lt;h2 id=&#34;finding-and-using-the-sqlite3-library&#34;&gt;Finding and using the sqlite3 library&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#finding-and-using-the-sqlite3-library&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In CMake parlance, &lt;code&gt;sqlite3&lt;/code&gt; is no longer a &amp;ldquo;regular&amp;rdquo; target, since it does not know how it was built.&lt;/p&gt;
&lt;p&gt;So we need to create an &lt;em&gt;imported&lt;/em&gt; target, and set the &lt;code&gt;IMPORTED_LOCATION&lt;/code&gt; and &lt;code&gt;INTERFACE_INCLUDE_DIRECTORIES&lt;/code&gt; properties on it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;project&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;ChuckNorris&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;add_library&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;sqlite3&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;STATIC&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;IMPORTED&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;set_target_properties&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;sqlite3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;PROPERTIES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;IMPORTED_LOCATION&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;/path/to/sqlite3-&amp;lt;version&amp;gt;/lib/libsqlite3.a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;INTERFACE_INCLUDE_DIRECTORIES&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;/path/to/sqlite3-&amp;lt;version&amp;gt;/include&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;add_library&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;chucknorris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that &lt;code&gt;/path/to/sqlite3&lt;/code&gt; is &lt;em&gt;an hard-coded absolute path&lt;/em&gt; to the folder we used to compile &lt;code&gt;sqlite3&lt;/code&gt; by hand.&lt;/p&gt;
&lt;p&gt;Obviously, hard-coded paths are bad, but this allows us to use &lt;code&gt;target_link_libraries&lt;/code&gt; to add a dependency between our &lt;code&gt;ChuckNorris&lt;/code&gt; library and the imported target, the same way we did to link &lt;code&gt;cpp_demo&lt;/code&gt; with &lt;code&gt;ChuckNorris&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;target_link_libraries&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;chucknorris&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;sqlite3&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s build the ChuckNorris project again:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ cmake -GNinja ../..
$ ninja -v
Build CXX object ChuckNorris.cpp.o
/bin/c++
  ../../src/ChuckNorris.cpp
  -I../../include
  -isystem /path/to/sqlite-&amp;lt;version&amp;gt;/include
  -o ChuckNorris.cpp.o
  ...
Linking CXX executable cpp_demo
/bin/c++
  main.cpp.o
  -o cpp_demo
  libchucknorris.a
  /path/to/sqlite-&amp;lt;version&amp;gt;/lib/sqlite3.a
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can see that CMake added the include path of sqlite3 in a &lt;code&gt;-isystem&lt;/code&gt; flag&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; when compiling &lt;code&gt;ChuckNorris.cpp&lt;/code&gt;, and that it added the &lt;code&gt;libsqlite3.a&lt;/code&gt; file when linking the &lt;code&gt;cpp_demo&lt;/code&gt; executable.&lt;/p&gt;
&lt;p&gt;On my machine, I still got a build failure:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Linking CXX executable cpp_demo
FAILED: cpp_demo
/bin/c++
  main.cpp.o
  -o cpp_demo
  libchucknorris.a
  /path/to/sqlite-&amp;lt;version&amp;gt;/libsqlite3.a

libsqlite3.a(sqlite3.o): In function `pthreadMutexAlloc&amp;#39;:
sqlite3.c:(.text+0x4275): undefined reference to `pthread_mutexattr_init&amp;#39;
...
libsqlite3.a(sqlite3.o): In function `unixDlOpen&amp;#39;:
sqlite3.c:(.text+0x10bd8): undefined reference to `dlopen&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What&amp;rsquo;s going on?&lt;/p&gt;
&lt;p&gt;Turns out that, on Linux at least, sqlite3 depends on two other libraries, namely &lt;code&gt;pthread&lt;/code&gt; and &lt;code&gt;dl&lt;/code&gt;. (This is common enough that I was able to guess the name of the libraries from the names of the missing symbols in the error message)&lt;/p&gt;
&lt;p&gt;We can fix our compilation failure by telling CMake about the dependency from &lt;code&gt;sqlite3&lt;/code&gt;  to &lt;code&gt;pthread&lt;/code&gt; and &lt;code&gt;dl&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;CMAKE_SYSTEM_NAME&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;STREQUAL&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Linux&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#24909d&#34;&gt;set_target_properties&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;sqlite3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;PROPERTIES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ed9d13&#34;&gt;INTERFACE_LINK_LIBRARIES&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;dl;pthread&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   )&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;endif&lt;/span&gt;()&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ninja -v
/bin/c++
  main.cpp.o
  -o cpp_demo
  libchucknorris.a
  /path/to/sqlite-&amp;lt;version&amp;gt;/lib/libsqlite3.a
  -ldl
  -lpthread
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That was not trivial, and we had to hard-code the location of the sqlite3 sources.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s now see how conan can help us using sqlite3 more easily.&lt;/p&gt;
&lt;h1 id=&#34;installing-conan&#34;&gt;Installing conan&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#installing-conan&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Conan is written in Python and you can install it with &lt;code&gt;pip&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python3 -m pip install conan --user
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Afterwards, you should add the directory where the &lt;code&gt;conan&lt;/code&gt; binary has been installed in your &lt;code&gt;PATH&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux: &lt;code&gt;export PATH=&amp;quot;${HOME}/.local/bin:${PATH}&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;macOS: &lt;code&gt;export PATH=&amp;quot;${HOME}/Library/Python3.x/bin:${PATH}&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Windows: nothing to do ;-)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conan lets you write &lt;em&gt;recipes&lt;/em&gt; and upload &lt;em&gt;binary packages&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A recipe is a piece of Python code that is used to build a package; and a package is simply an archive containing pre-compiled binaries.&lt;/p&gt;
&lt;p&gt;In the conan world, any user can publish recipes and binary packages for any library. (Many package managers use a &amp;ldquo;first come, first served&amp;rdquo; approach to package names, but not conan).&lt;/p&gt;
&lt;p&gt;As many other package managers, conan can look for packages in multiple locations called &lt;em&gt;remotes&lt;/em&gt;: all you need is to host a &lt;a href=&#34;http://docs.conan.io/en/latest/uploading_packages/running_your_server.html&#34;&gt;conan server&lt;/a&gt; somewhere.&lt;/p&gt;
&lt;p&gt;By default, conan comes with the &lt;code&gt;conan-center&lt;/code&gt; remote pre-configured.&lt;/p&gt;
&lt;h1 id=&#34;creating-a-conanfiletxt&#34;&gt;Creating a conanfile.txt&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#creating-a-conanfiletxt&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Conan uses a simple configuration file format where you can specify the dependencies and some &amp;ldquo;generators&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cfg&#34; data-lang=&#34;cfg&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[requires]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;sqlite3/3.21.0@bincrafters/stable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[generators]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;cmake&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The string &lt;code&gt;sqlite3/3.21@bincrafters/stable&lt;/code&gt; is called a &lt;em&gt;reference&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s the name: &lt;code&gt;sqlite3&lt;/code&gt;, the version: &lt;code&gt;3.21&lt;/code&gt;, a user: &lt;code&gt;bincrafters&lt;/code&gt; and a channel: &lt;code&gt;stable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can think of channels as branches: the &lt;code&gt;stable&lt;/code&gt; channel indicates that the recipes and binary packages have come through at least minimal quality assurance. (This is true for any package coming from the &lt;code&gt;conan-center&lt;/code&gt; remote inside the stable channel).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cmake&lt;/code&gt; generator tells conan to generate some files that contain information about the dependencies that are usable by CMake.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how to invoke conan:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ conan install ../..
sqlite3/3.21.0@bincrafters/stable: Not found in local cache, looking in remotes...
sqlite3/3.21.0@bincrafters/stable: Trying with &amp;#39;conan-center&amp;#39;...
...
PROJECT: Installing /path/to/conanfile.txt
Requirements
    sqlite3/3.21.0@bincrafters/stable from &amp;#39;conan-center&amp;#39;
Packages
    sqlite3/3.21.0@bincrafters/stable:6ae331b72e7e265ca2a3d1d8246faf73aa030238
PROJECT: Retrieving package 6ae331b72e7e265ca2a3d1d8246faf73aa030238
...
PROJECT: Generator cmake created conanbuildinfo.cmake
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Several things happened here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;First conan looked for the package in the local cache and did not find it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It used a &lt;em&gt;remote&lt;/em&gt;  called &lt;code&gt;conan-center&lt;/code&gt; and found a compatible package there with a certain ID (&lt;code&gt;6ae331b72e7e265ca2a3d1d8246faf73aa030238&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then it downloaded the binary package from the remote and stored it in the cache.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finally, it generated a file called &lt;code&gt;conanbuildinfo.cmake&lt;/code&gt; in the build folder.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;adapt-cmakeliststxt&#34;&gt;Adapt CMakeLists.txt&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#adapt-cmakeliststxt&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We can then revert our changes in the &lt;code&gt;CMakeLists.txt&lt;/code&gt; file and instead include the file conan generated for us, using the &lt;code&gt;include()&lt;/code&gt; CMake function and the predefined CMake variable &lt;code&gt;CMAKE_BINARY_DIR&lt;/code&gt; that points to the build folder:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;include&lt;/span&gt;(${&lt;span style=&#34;color:#40ffff&#34;&gt;CMAKE_BINARY_DIR&lt;/span&gt;}&lt;span style=&#34;color:#ed9d13&#34;&gt;/conanbuildinfo.cmake&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we invoke the &lt;code&gt;conan_basic_setup()&lt;/code&gt; method and refer to the targets defined by conan using the &lt;code&gt;CONAN_PKG::&lt;/code&gt; prefix:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;project&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;ChuckNorris&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;CMAKE_CXX_STANDARD&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;11&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;include&lt;/span&gt;(${&lt;span style=&#34;color:#40ffff&#34;&gt;CMAKE_BINARY_DIR&lt;/span&gt;}&lt;span style=&#34;color:#ed9d13&#34;&gt;/conanbuildinfo.cmake&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;conan_basic_setup&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;TARGETS&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;target_link_libraries&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;chucknorris&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;CONAN_PKG::sqlite3&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now call &lt;code&gt;cmake&lt;/code&gt; and &lt;code&gt;ninja&lt;/code&gt; as we did in the end of the previous part:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cmake -GNinja ../..
...
-- Conan: Using cmake targets configuration
-- Library sqlite3 found /home/dmerej/.conan/data/.../lib/libsqlite3.a
...
$ ninja
[1/3] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[2/3] Linking CXX static library lib/libchucknorris.a
[3/3] Linking CXX executable bin/cpp_demo
$ ./bin/cpp_demo
The easiest way to determine Chuck Norris&amp;#39;s age is to cut him
in half and count the rings.
$ ./bin/cpp_demo
If, by some incredible space-time paradox, Chuck Norris would ever fight
himself, he&amp;#39;d win. Period.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Seems to work!&lt;/p&gt;
&lt;p&gt;In the next articles, we&amp;rsquo;ll &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-3-a-c-wrapper/&#34;&gt;write a C wrapper on top of our C++ API&lt;/a&gt; and then use it to implement a &lt;code&gt;chucknorris&lt;/code&gt; module in Python.&lt;/p&gt;
&lt;p&gt;See you soon :)&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;The &lt;code&gt;-isystem&lt;/code&gt; flag works almost like the &lt;code&gt;-I&lt;/code&gt; flag. You can find all about the gory details in the gcc man page.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Let&#39;s Build Chuck Norris! - Part 1: CMake and Ninja</title>
      <link>https://dmerej.info/blog/post/chuck-norris-part-1-cmake-ninja/</link>
      <pubDate>Sat, 10 Mar 2018 14:22:53 +0100</pubDate>
      
      <guid>https://dmerej.info/blog/post/chuck-norris-part-1-cmake-ninja/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This is part 1 of the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-the-chuck-norris-project/&#34;&gt;Let&amp;rsquo;s Build Chuck Norris!&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;the-core-library&#34;&gt;The core library&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-core-library&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We want a &lt;code&gt;ChuckNorris&lt;/code&gt; class with a &lt;code&gt;getFact()&lt;/code&gt; method that returns a random Chuck Norris fact.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with a hard-coded answer for now:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;include/ChuckNorris.hpp&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#pragma once
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;ChuckNorris&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;public&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ChuckNorris();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std::string getFact();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;src/ChuckNorris.cpp&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;ChuckNorris.hpp&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ChuckNorris::ChuckNorris()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std::string ChuckNorris::getFact()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Chuck Norris can slam a revolving door.&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have a header in &lt;code&gt;include/ChuckNorris.hpp&lt;/code&gt; containing the class &lt;em&gt;declaration&lt;/em&gt;, and a file in &lt;code&gt;src/ChuckNorris.cpp&lt;/code&gt; containing the class &lt;em&gt;definition&lt;/em&gt;.&lt;/p&gt;
&lt;h1 id=&#34;the-test-program&#34;&gt;The test program&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-test-program&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;To make sure the library can indeed be used in other programs, let&amp;rsquo;s add a &lt;code&gt;src/main.cpp&lt;/code&gt; to check we manage to get the hard-coded fact:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;src/main.cpp&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;ChuckNorris.hpp&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;main&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ChuckNorris chuckNorris;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std::string fact = chuckNorris.getFact();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  std::cout &amp;lt;&amp;lt; fact &amp;lt;&amp;lt; std::endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All we have to do is run the program without arguments, and check that something gets displayed. That will probably be enough to check our library works.&lt;/p&gt;
&lt;h1 id=&#34;targets&#34;&gt;Targets&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#targets&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s enumerate what we have to do now to build everything:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make sure that the &lt;code&gt;include/&lt;/code&gt; directory is used when we compile code in &lt;code&gt;src/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Build a library using &lt;code&gt;src/ChuckNorris.cpp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Build an executable named &lt;code&gt;cpp_demo&lt;/code&gt; using &lt;code&gt;src/main.cpp&lt;/code&gt; that links with the above library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can say we have two &lt;em&gt;targets&lt;/em&gt;: a library called &lt;code&gt;chucknorris&lt;/code&gt;, and an executable named &lt;code&gt;cpp_demo&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the commands to build them look like on Linux:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Compile the .cpp file into a .o&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ g++ -c -I include/ src/ChuckNorris.cpp -o libchucknorris.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Create an archive containing the .o&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ar cr libchucknorris.a libchucknorris.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Compile main.cpp into main.o&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ g++ -c -I include/ src/main.cpp -o main.o
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Tell g++ to link everything into an executable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ g++ main.o libchucknorris.a -o cpp_demo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# Run the executable we&amp;#39;ve just built:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$./cpp_demo
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Chuck Norris can slam a revolving door.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Phew!&lt;/p&gt;
&lt;p&gt;Keeping track of all this by hand would get tedious very soon, but fortunately there are tools that can help us.&lt;/p&gt;
&lt;h1 id=&#34;cmake&#34;&gt;CMake&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#cmake&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;CMake lets us describe the targets we want to build in code.&lt;/p&gt;
&lt;p&gt;We do it by writing the following code in a file named &lt;code&gt;CMakeLists.txt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;cmake_minimum_required&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;3.10&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;CMAKE_CXX_STANDARD&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;11&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;project&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;ChuckNorris&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;add_library&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;chucknorris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;include/ChuckNorris.hpp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;src/ChuckNorris.cpp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;target_include_directories&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;chucknorris&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;PUBLIC&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;include&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;add_executable&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;cpp_demo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ed9d13&#34;&gt;src/main.cpp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#24909d&#34;&gt;target_link_libraries&lt;/span&gt;(&lt;span style=&#34;color:#ed9d13&#34;&gt;cpp_demo&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;chucknorris&lt;/span&gt;)&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;add_library&lt;/code&gt; and &lt;code&gt;add_executable&lt;/code&gt; commands describe the two targets (named &lt;code&gt;chucknorris&lt;/code&gt; and &lt;code&gt;cpp_demo&lt;/code&gt;) and the sources used to build them, and the &lt;code&gt;target_link_libraries&lt;/code&gt; command tells CMake that &lt;code&gt;cpp_demo&lt;/code&gt; &lt;em&gt;depends&lt;/em&gt; on &lt;code&gt;chucknorris&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;target_include_directories&lt;/code&gt; informs CMake that there are header files in the &lt;code&gt;include&lt;/code&gt; directories that should be used both when builing the library itself, but also by consumers of the library. (We used the &lt;code&gt;-I include/&lt;/code&gt; flag both for building &lt;code&gt;libchucknorris.o&lt;/code&gt; and &lt;code&gt;main.co&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;If the headers were used only to compile the library, we would have used the &lt;code&gt;PRIVATE&lt;/code&gt; keyword, and if they were used only by consumers of the library, we would have used the &lt;code&gt;INTERFACE&lt;/code&gt; keyword instead. You can read more about this in the &lt;a href=&#34;https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html&#34;&gt;CMake documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also note how we set the &lt;code&gt;CMAKE_CXX_STANDARD&lt;/code&gt; variable. This will allow us to use modern C++ features (available in C++ 11 or later) such as the &lt;code&gt;auto&lt;/code&gt; keyword or raw string literals later on.&lt;/p&gt;
&lt;h1 id=&#34;ninja&#34;&gt;Ninja&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#ninja&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Now that we have described what we want to build and how, we still need to perform the build itself.&lt;/p&gt;
&lt;p&gt;CMake does not know how to &lt;em&gt;actually&lt;/em&gt; perform the build. Instead it generates files that will be used by an &lt;em&gt;other&lt;/em&gt; tool. It&amp;rsquo;s called a CMake &lt;em&gt;generator&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;There are plenty of generators available, but for now we&amp;rsquo;ll only talk about Ninja. I&amp;rsquo;ve already explain why I prefer using CMake with Ninja in an &lt;a href=&#34;https://dmerej.info/blog/post/cmake-visual-studio-and-the-command-line/&#34;&gt;other blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our first attempt, we generated all the binaries (&lt;code&gt;libchucknorris.a&lt;/code&gt;, the &lt;code&gt;.o&lt;/code&gt; files and the &lt;code&gt;cpp_demo&lt;/code&gt; executable) directly in the current working directory. It&amp;rsquo;s cleaner to have them put inside a dedicated &lt;em&gt;build folder&lt;/em&gt; instead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We&amp;rsquo;ll only have to put the build folder into our &lt;code&gt;.gitignore&lt;/code&gt; file, instead of a bunch of files&lt;/li&gt;
&lt;li&gt;If we want to, we can have several build folders, all using the same sources, but using different compilers or flags without risking mixing incompatible binaries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So let&amp;rsquo;s create a folder named &lt;code&gt;build/default&lt;/code&gt; and call CMake, asking it to use the Ninja generator. CMake uses the current working directory as the build folder, and you must specify the path to the folder containing the &lt;code&gt;CMakeLists.txt&lt;/code&gt; file as the last argument on the command line:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ mkdir -p build/default
$ cd build/default
$ cmake -GNinja ../..
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now we use ninja to build build and run our executable from the build folder:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ cd build/default
$ ninja
[1/4] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[2/4] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[3/4] Linking CXX static library libchucknorris.a
[4/4] Linking CXX executable cpp_demo
$ ./cpp_demo
Chuck Norris can slam a revolving door.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Done!&lt;/p&gt;
&lt;p&gt;Note that CMake and Ninja cooperate so that you only rebuild what&amp;rsquo;s need to be rebuilt.&lt;/p&gt;
&lt;p&gt;If we change just the &lt;code&gt;main.cpp&lt;/code&gt;, we just have to rebuild &lt;code&gt;main.cpp.o&lt;/code&gt; and relink the &lt;code&gt;cpp_demo&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ninja
[1/2] Building CXX object CMakeFiles/cpp_demo.dir/src/main.cpp.o
[2/2] Linking CXX executable cpp_demo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But if we change &lt;code&gt;ChuckNorris.cpp&lt;/code&gt;, everything &lt;em&gt;except&lt;/em&gt; &lt;code&gt;main.cpp.o&lt;/code&gt; needs to be rebuilt:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[1/3] Building CXX object CMakeFiles/chucknorris.dir/src/ChuckNorris.cpp.o
[2/3] Linking CXX static library libchucknorris.a
[3/3] Linking CXX executable cpp_demo
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And if we change the &lt;code&gt;CMakeLists.txt&lt;/code&gt; file, Ninja will re-run CMake for us:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ ninja
[0/x] Re-running CMake...
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build/default
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&amp;rsquo;s all for the first part. Stay tuned for &lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-2-sqlite-conan/&#34;&gt;part 2&lt;/a&gt;, where we&amp;rsquo;ll introduce an external dependency and get rid of the hard-coded fact.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing the &#34;Let&#39;s Build Chuck Norris!&#34; Project</title>
      <link>https://dmerej.info/blog/post/introducing-the-chuck-norris-project/</link>
      <pubDate>Sat, 10 Mar 2018 12:35:38 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/introducing-the-chuck-norris-project/</guid>
      <description>&lt;h1 id=&#34;the-chucknorris-library&#34;&gt;The ChuckNorris library&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-chucknorris-library&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The Chuck Norris library is written in C++ and contains a class able to give you random Chuck Norris facts when the &lt;code&gt;getFact()&lt;/code&gt; method is called:&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how to use it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&amp;lt;ChuckNorris.hpp&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cd2828;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ChuckNorris chuckNorris;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std::string fact = chuckNorris.getFact();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;note&#34;&gt;
  You will find all the source code on &lt;a href=&#34;https://github.com/dmerejkowsky/chucknorris&#34;&gt;GitHub&lt;/a&gt;.
&lt;/div&gt;
&lt;p&gt;
&lt;/p&gt;

&lt;h1 id=&#34;lets-build-chuck-norris&#34;&gt;Let&amp;rsquo;s build Chuck Norris!&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#lets-build-chuck-norris&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&amp;ldquo;Let&amp;rsquo;s Build Chuck Norris!&amp;rdquo; is a series of blog posts aiming at exploring various topics about C++ and build systems, and providing an example of the &lt;a href=&#34;http://videocortex.io/2017/salami-method/&#34;&gt;Salami method&lt;/a&gt; described by Adi Shavit.&lt;/p&gt;
&lt;p&gt;Here are all of them, in chronological order. Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-1-cmake-ninja/&#34;&gt;Part 1 - Using CMake and Ninja&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-2-sqlite-conan/&#34;&gt;Part 2 - Managing third-party dependencies with conan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-3-a-c-wrapper/&#34;&gt;Part 3 - Exposing a C API on top of C++ code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-4-python-ctypes/&#34;&gt;Part 4 - Using Python with ctypes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-5-python-cffi/&#34;&gt;Part 5 - Using cffi to build a Python extension&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-6-android-cross-compilation/&#34;&gt;Part 6 - Cross-compiling for Android&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-7-android-jna/&#34;&gt;Part 7 - Android and JNA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://dmerej.info/blog/post/chuck-norris-part-8-ios/&#34;&gt;Part 8 - Using C++ in an iOS application&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Porting to pytest: a practical example</title>
      <link>https://dmerej.info/blog/post/porting-to-pytest-a-practical-example/</link>
      <pubDate>Thu, 01 Mar 2018 16:34:19 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/porting-to-pytest-a-practical-example/</guid>
      <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The other day I was following the &lt;a href=&#34;https://docs.djangoproject.com/en/2.0/intro/&#34;&gt;django tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you never read the tutorial, or don&amp;rsquo;t want to, here&amp;rsquo;s what you need to know:&lt;/p&gt;
&lt;p&gt;We have a django project containing an application called &lt;code&gt;polls&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We have two model objects representing questions and choices.&lt;/p&gt;
&lt;p&gt;Each question has a publication date, a text, and a list of choices.&lt;/p&gt;
&lt;p&gt;Each choice has a reference to an existing question (via a foreign key), a text, and a number of votes.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a view that shows a list of questions as links. Each link, when clicked displays the choices and has a form to let the user vote.&lt;/p&gt;
&lt;p&gt;The code is pretty straightforward:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# polls/models.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Question&lt;/span&gt;(models.Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    question_text = models.CharField(max_length=&lt;span style=&#34;color:#3677a9&#34;&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pub_date = models.DateTimeField(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;date published&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;was_published_recently&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        now = timezone.now()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        two_days_ago = now - datetime.timedelta(days=&lt;span style=&#34;color:#3677a9&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; two_days_ago &amp;lt; self.pub_date &amp;lt;= now
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Choice&lt;/span&gt;(models.Model):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    question = models.ForeignKey(Question, on_delete=models.CASCADE)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    choice_text = models.CharField(max_length=&lt;span style=&#34;color:#3677a9&#34;&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Everything went smoothly until I arrived at the &lt;a href=&#34;https://docs.djangoproject.com/en/2.0/intro/tutorial05/&#34;&gt;part 5&lt;/a&gt;, about automated testing, where I read the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sometimes it may seem a chore to tear yourself away from your productive, creative programming work to face the unglamorous and unexciting business of writing tests, particularly when you know your code is working properly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, allow me to retort!&lt;/p&gt;
&lt;h1 id=&#34;starting-point-using-tests-from-the-documentation&#34;&gt;Starting point: using tests from the documentation&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#starting-point-using-tests-from-the-documentation&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s what the tests looks like when extracted from the django documentation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;django.utils&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; timezone
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;django.test&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; TestCase
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;.models&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; Question
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;QuestionModelTests&lt;/span&gt;(TestCase):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_was_published_recently_with_future_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        was_published_recently() returns False for questions whose pub_date
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        is in the future.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        time = timezone.now() + datetime.timedelta(days=&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        future_question = Question(pub_date=time)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertIs(future_question.was_published_recently(), &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_was_published_recently_with_old_question&lt;/span&gt;(self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        was_published_recently() returns False for questions whose pub_date
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        is older than 1 day.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        time = timezone.now() - datetime.timedelta(days=&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;, seconds=&lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        old_question = Question(pub_date=time)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertIs(old_question.was_published_recently(), &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;False&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_was_published_recently_with_recent_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        was_published_recently() returns True for questions whose pub_date
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        is within the last day.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        time = timezone.now() - datetime.timedelta(hours=&lt;span style=&#34;color:#3677a9&#34;&gt;23&lt;/span&gt;, minutes=&lt;span style=&#34;color:#3677a9&#34;&gt;59&lt;/span&gt;, seconds=&lt;span style=&#34;color:#3677a9&#34;&gt;59&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        recent_question = Question(pub_date=time)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertIs(recent_question.was_published_recently(), &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;create_question&lt;/span&gt;(question_text, days):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    Create a question with the given `question_text` and published the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    given number of `days` offset to now (negative for questions published
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    in the past, positive for questions that have yet to be published).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    time = timezone.now() + datetime.timedelta(days=days)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; Question.objects.create(question_text=question_text, pub_date=time)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;QuestionIndexViewTests&lt;/span&gt;(TestCase):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_no_questions&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        If no questions exist, an appropriate message is displayed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertEqual(response.status_code, &lt;span style=&#34;color:#3677a9&#34;&gt;200&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertContains(response, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;No polls are available.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertQuerysetEqual(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_past_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        Questions with a pub_date in the past are displayed on the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        index page.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertQuerysetEqual(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;Question: Past question.&amp;gt;&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_future_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        Questions with a pub_date in the future aren&amp;#39;t displayed on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        the index page.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Future question.&amp;#34;&lt;/span&gt;, days=&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertContains(response, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;No polls are available.&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertQuerysetEqual(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_future_question_and_past_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        Even if both past and future questions exist, only past questions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        are displayed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Future question.&amp;#34;&lt;/span&gt;, days=&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertQuerysetEqual(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;Question: Past question.&amp;gt;&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_two_past_questions&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        The questions index page may display multiple questions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;        &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question 1.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question 2.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.assertQuerysetEqual(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;Question: Past question 2.&amp;gt;&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;Question: Past question 1.&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can run them using the &lt;code&gt;manage.py&lt;/code&gt; script and check they all pass:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; python manage.py &lt;span style=&#34;color:#24909d&#34;&gt;test&lt;/span&gt; polls
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Creating test database for alias &amp;#39;default&amp;#39;...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;System check identified no issues (0 silenced).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;........
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;----------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Ran 8 tests in 0.017s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;OK
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Destroying test database for alias &amp;#39;default&amp;#39;...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK, tests do pass. Let&amp;rsquo;s try and improve them.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve set up &lt;a href=&#34;https://github.com/dmerejkowsky/django-polls&#34;&gt;a GitHub repository&lt;/a&gt; where you can follow the following steps commit by commit if you wish.&lt;/p&gt;
&lt;h1 id=&#34;step-one-setup-pytest&#34;&gt;Step one: setup pytest&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#step-one-setup-pytest&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve already told you &lt;a href=&#34;https://dmerej.info/blog/post/pytest-rocks/&#34;&gt;how much I love pytest&lt;/a&gt;, so let&amp;rsquo;s try to convert to &lt;code&gt;pytest&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The first step is to install &lt;code&gt;pytest-django&lt;/code&gt; and configure it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; pip install pytest pytest-django
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cfg&#34; data-lang=&#34;cfg&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# in pytest.ini&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;[pytest]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;mysite.settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;python_files&lt;/span&gt; = &lt;span style=&#34;color:#ed9d13&#34;&gt;tests.py test_*.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now run tests using &lt;code&gt;pytest&lt;/code&gt; directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; pytest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;========== test session starts ========
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;platform linux -- Python 3.5.3, pytest-3.3.1, py-1.5.2, pluggy-0.6.0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;Django settings: mysite.settings (from ini file)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;rootdir: /home/dmerej/src/dmerej/django-polls, inifile: pytest.ini
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;plugins: django-3.1.2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;collected 8 items
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;polls/tests.py ........   [100%]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;======== 8 passed in 0.18 seconds =======
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;step-two-rewrite-assertions&#34;&gt;Step two: rewrite assertions&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#step-two-rewrite-assertions&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;We can now use &lt;code&gt;pytest&lt;/code&gt; magic to rewrite all &amp;ldquo;easy&amp;rdquo; assertions such as &lt;code&gt;assertFalse&lt;/code&gt; or &lt;code&gt;assertEquals&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- self.assertFalse(future_question.was_published_recently())
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ assert not future_question.was_published_recently()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Already we can see several improvements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The code is more readable and follows PEP8&lt;/li&gt;
&lt;li&gt;The error messages are more detailed:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;#&lt;/span&gt; Before, with unittest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; python manage.py &lt;span style=&#34;color:#24909d&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;    def test_was_published_recently_with_future_question(self):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;&amp;gt;&lt;/span&gt;       self.assertFalse(question.was_published_recently())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;E       AssertionError: True is not false
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a61717;background-color:#e3d2d2&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;#&lt;/span&gt; After, with pytest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; pytest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;&amp;gt;&lt;/span&gt;       assert not question.was_published_recently()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;E       AssertionError: assert not True
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ccc&#34;&gt;E        +  where True = &amp;lt;bound method was_published_recently() of Question&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then we have to deal with &lt;code&gt;assertContains&lt;/code&gt; and &lt;code&gt;assertQuerysetEqual&lt;/code&gt; which look a bit django-specific.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;assertContains&lt;/code&gt; I quickly managed to find I could use &lt;code&gt;response.rendered_content&lt;/code&gt; instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- self.assertContains(response, &amp;#34;No polls are available.&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ assert &amp;#34;No polls are available.&amp;#34; in response.rendered_content
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For &lt;code&gt;assertQuerysetEqual&lt;/code&gt; it was a bit harder.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_past_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.assertQuerysetEqual(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;&amp;lt;Question: Past question.&amp;gt;&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This test checks that the context used to generate the response was passed correct &lt;code&gt;latest_question_list&lt;/code&gt; value.&lt;/p&gt;
&lt;p&gt;But it does so by checking the &lt;em&gt;string representation&lt;/em&gt; of the &lt;code&gt;Question&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Thus, it will break as soon as &lt;code&gt;Question.__str__&lt;/code&gt; changes, which is not ideal.&lt;/p&gt;
&lt;p&gt;So instead, we can write something like this and check for the content of the &lt;code&gt;question_text&lt;/code&gt; attribute directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_past_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response = self.client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    actual_questions = response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(actual_questions) == &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    actual_question = actual_questions[&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; actual_question.question_text == &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While we&amp;rsquo;re at it, we can introduce small helper functions to make the tests easier to read:&lt;/p&gt;
&lt;p&gt;For instance, the string &lt;code&gt;No polls are available&lt;/code&gt; is hard-coded twice in the tests. Let&amp;rsquo;s introduce a &lt;code&gt;assert_no_polls&lt;/code&gt; helper:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;assert_no_polls&lt;/span&gt;(text):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;No polls are available&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; text
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;- assert &amp;#34;No polls are available.&amp;#34; in response.rendered_content
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ assert_no_polls(response.rendered_content)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An other hard-coded string is &lt;code&gt;polls:index&lt;/code&gt;, so let&amp;rsquo;s introduce &lt;code&gt;get_latest_list&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get_latest_list&lt;/span&gt;(client):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    response = client.get(reverse(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;polls:index&amp;#39;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; response.status_code == &lt;span style=&#34;color:#3677a9&#34;&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; response.context[&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;latest_question_list&amp;#39;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how we embedded the status code check directly in our helper, so we don&amp;rsquo;t have to repeat the check in each test.&lt;/p&gt;
&lt;p&gt;Also, note that if the name of the route (&lt;code&gt;polls:index&lt;/code&gt;) or the  name of the context key used in the template (&lt;code&gt;latest_question_list&lt;/code&gt;) ever changes, we&amp;rsquo;ll just need to update the test code in one place.&lt;/p&gt;
&lt;p&gt;Then, we can further simplify our assertions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;assert_question_list_equals&lt;/span&gt;(actual_questions, expected_texts):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(actual_questions) == &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(expected_texts)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; actual_question, expected_text &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;zip&lt;/span&gt;(actual_questions, expected_texts):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; actual_question.question_text == expected_text
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_past_question&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    create_question(question_text=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question.&amp;#34;&lt;/span&gt;, days=-&lt;span style=&#34;color:#3677a9&#34;&gt;30&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    latest_list = get_latest_list(self.client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    assert_question_list_equals(latest_list, [&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Past question.&amp;#34;&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;step-three-move-code-out-of-classes&#34;&gt;Step three: move code out of classes&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#step-three-move-code-out-of-classes&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The nice thing about &lt;code&gt;pytest&lt;/code&gt; is that you don&amp;rsquo;t need to put your tests as methods of a class, you can just write
test functions directly.&lt;/p&gt;
&lt;p&gt;So we just remove the &lt;code&gt;self&lt;/code&gt; parameter, indent back all the code, and we are (almost) good to go.&lt;/p&gt;
&lt;p&gt;We already got rid of all the &lt;code&gt;self.assert*&lt;/code&gt; methods, so the last thing to do is pass the Django test client as a parameter instead of using &lt;code&gt;self.client&lt;/code&gt;. (That&amp;rsquo;s how &lt;a href=&#34;https://docs.pytest.org/en/latest/fixture.html&#34;&gt;pytest fixtures&lt;/a&gt; work):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    def test_two_past_questions(self):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-        latest_list = get_latest_list(self.client)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+ def test_no_questions(client):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+    latest_list = get_latest_list(client)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But then we encounter an unexpected failure:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Polls/tests.py:34: in create_question
    return Question.objects.create(question_text=question_text, pub_date=time)

    ...

&amp;gt;       self.ensure_connection()
E       Failed: Database access not allowed, use the &amp;#34;django_db&amp;#34; mark, or the &amp;#34;db&amp;#34; or &amp;#34;transactional_db&amp;#34; fixtures to enable it.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Back when we used &lt;code&gt;python manage.py test&lt;/code&gt;, django&amp;rsquo;s &lt;code&gt;manage.py&lt;/code&gt; script was implicitly creating a test database for us.&lt;/p&gt;
&lt;p&gt;When we use &lt;code&gt;pytest&lt;/code&gt;, we have to be explicit about it and add a special marker:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;pytest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# No change here, no need for a DB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_was_published_recently_with_old_question&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# We use create_question, which in turn calls Question.objects.create(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# so we need a database here:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ffa500&#34;&gt;@pytest.mark.django_db&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_no_questions&lt;/span&gt;(client):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;True, this is a bit annoying, but note that if we only want to test the models themselves (like the &lt;code&gt;was_published_recently()&lt;/code&gt; method), we can just use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; pytest -k was_published_recently
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and no database will be created &lt;em&gt;at all&lt;/em&gt;.&lt;/p&gt;
&lt;h1 id=&#34;step-four-get-rid-of-doc-strings&#34;&gt;Step four: Get rid of doc strings&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#step-four-get-rid-of-doc-strings&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I don&amp;rsquo;t like doc strings, &lt;em&gt;except&lt;/em&gt; when I&amp;rsquo;m implementing a very public API. There, I&amp;rsquo;ve said it.&lt;/p&gt;
&lt;p&gt;I very much prefer when the code is &amp;ldquo;self-documenting&amp;rdquo;, &lt;em&gt;especially&lt;/em&gt; when it&amp;rsquo;s test code.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&#34;http://blog.cleancoder.com&#34;&gt;Uncle Bob&lt;/a&gt; said, &amp;ldquo;tests should read like well-written specifications&amp;rdquo;. So let&amp;rsquo;s try some refactoring.&lt;/p&gt;
&lt;p&gt;We can start with more meaningful variable names, and have more fun with the examples:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;def test_was_published_recently_with_old_question():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   time = timezone.now() - datetime.timedelta(days=1, seconds=1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   old_question = Question(pub_date=time)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   last_year = timezone.now() - datetime.timedelta(days=365)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   old_question = Question(&amp;#39;Why is there something instead of nothing?&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+                            pub_date=last_year)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;&lt;/span&gt;    assert not old_question.was_published_recently()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;def test_was_published_recently_with_recent_question():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   time = timezone.now() - datetime.timedelta(days=1, seconds=1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-   recent_question = Question(pub_date=time)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   last_night = timezone.now() - datetime.timedelta(hours=10)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+   recent_question = Question(&amp;#39;Dude, where is my car?&amp;#39;, pub_date=last_night)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Time and date code is always tricky, and a negative number of days does not really make sense, so let&amp;rsquo;s make things easier to reason about:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;n_days_ago&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; timezone.now() - datetime.timedelta(days=n)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;n_days_later&lt;/span&gt;(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; timezone.now() + datetime.timedelta(days=n)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Also &lt;code&gt;create_question&lt;/code&gt; is coupled with the &lt;code&gt;Question&lt;/code&gt; model, so let&amp;rsquo;s use the same names for the parameter names and the model&amp;rsquo;s attributes.&lt;/p&gt;
&lt;p&gt;And since we may want to create question without caring about the publication date, let&amp;rsquo;s make it an optional parameter:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;create_question&lt;/span&gt;(question_text, *, pub_date=&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;not&lt;/span&gt; pub_date:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        pub_date = timezone.now()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Code becomes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-patch&#34; data-lang=&#34;patch&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;-    create_question(question_text=&amp;#34;Past question.&amp;#34;, days=-30)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#d22323&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#589819&#34;&gt;+    create_question(question_text=&amp;#34;Past question.&amp;#34;, pub_date=n_days_ago(30))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, let&amp;rsquo;s add a new test to see if our helpers really work:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ffa500&#34;&gt;@pytest.mark.django_db&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_latest_five&lt;/span&gt;(client):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;range&lt;/span&gt;(&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#3677a9&#34;&gt;10&lt;/span&gt;):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        pub_date = n_days_ago(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Question #&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;%s&lt;/span&gt;&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&lt;/span&gt; % i, pub_date=pub_date)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    latest_list = get_latest_list(client)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(actual_list) == &lt;span style=&#34;color:#3677a9&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do you still think this test needs a docstring ?&lt;/p&gt;
&lt;h1 id=&#34;step-five-fun-with-selenium&#34;&gt;Step five: fun with selenium&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#step-five-fun-with-selenium&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&#34;selenium-basics&#34;&gt;Selenium basics&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#selenium-basics&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.seleniumhq.org/&#34;&gt;Selenium&lt;/a&gt; deals with browser automation.&lt;/p&gt;
&lt;p&gt;Here we are going to use the Python bindings, which allow us to start &lt;code&gt;Firefox&lt;/code&gt; or &lt;code&gt;Chrome&lt;/code&gt; and control them with code.&lt;/p&gt;
&lt;p&gt;(In both cases, you&amp;rsquo;ll need to install a separate binary: &lt;code&gt;geckodriver&lt;/code&gt; or &lt;code&gt;chromedriver&lt;/code&gt; respectively)&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how you can use &lt;code&gt;selenium&lt;/code&gt; do visit a web page and click the first link:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;selenium.webdriver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;driver = selenium.webdriver.Firefox()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;driver = selenium.webdriver.Chrome()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;driver.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;http://example.com&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;link = driver.find_element_by_tag_name(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;link.click()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-live-server-test-case&#34;&gt;The Live Server Test Case&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#the-live-server-test-case&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Django exposes a &lt;code&gt;LiveServerTestCase&lt;/code&gt;, but no &lt;code&gt;LiveServer&lt;/code&gt; object or similar.&lt;/p&gt;
&lt;p&gt;The code is a bit tricky because it needs to spawn a &amp;ldquo;real&amp;rdquo; server in a separate thread, make sure it uses a free port,  and tell the selenium driver to use an URL like &lt;code&gt;http://localhost:32456&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Fear not, &lt;code&gt;pytest&lt;/code&gt; also works fine in this case. We just have to be careful to use &lt;code&gt;super()&lt;/code&gt; in the set up and tear down methods so that the code from &lt;code&gt;LiveServerTestCase&lt;/code&gt; gets executed properly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;urllib.parse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;TestPolls&lt;/span&gt;(LiveServerTestCase):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serialized_rollback = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;setUp&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt;().setUp()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver = selenium.webdriver.Firefox()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;tearDown&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver.close()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt;().tearDown()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_home_no_polls&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        url = urllib.parse.urljoin(self.live_server_url, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/polls&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver.get(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        assert_no_polls(self.browser.page_source)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you&amp;rsquo;re wondering why we need &lt;code&gt;serialized_rollback=True&lt;/code&gt;, the answer is in &lt;a href=&#34;https://docs.djangoproject.com/en/2.0/topics/testing/tools/#transactiontestcase&#34;&gt;the documentation&lt;/a&gt;. Without it we may have weird database errors during tests.&lt;/p&gt;
&lt;p&gt;Our first test is pretty basic: we ask the browser to visit the &lt;code&gt;&#39;polls/&lt;/code&gt; URL and check no polls are shown, re-using our &lt;code&gt;assert_no_polls&lt;/code&gt; helper function from before.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s also check we are shown links to the questions if they are some, and can click on them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;TestPolls&lt;/span&gt;(LiveServerTestCase):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_home_list_polls&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;One?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Two?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        create_question(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Three?&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        url = urllib.parse.urljoin(self.live_server_url, &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;polls/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver.get(url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        first_link = self.driver.find_element_by_tag_name(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        first_link.click()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;Three?&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;in&lt;/span&gt; self.driver.page_source
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;lets-build-a-facade&#34;&gt;Let&amp;rsquo;s build a facade&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#lets-build-a-facade&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;find_element_by_*&lt;/code&gt; methods of the selenium API are a bit tedious to use: thery are called &lt;code&gt;find_element_by_tag_name&lt;/code&gt;, &lt;code&gt;find_element_by_class_name&lt;/code&gt;, &lt;code&gt;find_element_by_id&lt;/code&gt; and so on&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s write a &lt;code&gt;Browser&lt;/code&gt; class to hide those behind a more &amp;ldquo;Pythonic&amp;rdquo; API:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# old&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;link = driver.find_element_by_tag_name(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;link&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;form = driver.find_element_by_id(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;form-id&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;link = driver.find_element(tag_name=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;link&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;form = driver.find_element(&lt;span style=&#34;color:#24909d&#34;&gt;id&lt;/span&gt;=&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;form-id&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(This is known as the &amp;ldquo;facade&amp;rdquo; design pattern)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Browser&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;&amp;#34;&amp;#34; A nice facade on top of selenium stuff &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, driver):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver = driver
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;find_element&lt;/span&gt;(self, **kwargs):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;assert&lt;/span&gt; &lt;span style=&#34;color:#24909d&#34;&gt;len&lt;/span&gt;(kwargs) == &lt;span style=&#34;color:#3677a9&#34;&gt;1&lt;/span&gt;   &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# we want exactly one named parameter here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name, value = &lt;span style=&#34;color:#24909d&#34;&gt;list&lt;/span&gt;(kwargs.items())[&lt;span style=&#34;color:#3677a9&#34;&gt;0&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        func_name = &lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;find_element_by_&amp;#34;&lt;/span&gt; + name
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        func = &lt;span style=&#34;color:#24909d&#34;&gt;getattr&lt;/span&gt;(self.driver, func_name)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; func(value)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note how we have to convert the &lt;code&gt;items()&lt;/code&gt; to a real list just to get the first element&amp;hellip; (In Python2, &lt;code&gt;kwargs.items()[0]&lt;/code&gt; would have worked just fine). Please tell me if you find a better way &amp;hellip;&lt;/p&gt;
&lt;p&gt;Note also how we &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; just inherit from &lt;code&gt;selenium.webdriver.Firefox&lt;/code&gt;. The goal is to expose a &lt;em&gt;different&lt;/em&gt; API, so using composition here is better.&lt;/p&gt;
&lt;p&gt;If we need access to attributes of &lt;code&gt;self.driver&lt;/code&gt;, we can just use a property, like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Browser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@property&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;page_source&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;return&lt;/span&gt; self.driver.page_source
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if we need to call a method directly to the underlying object, we can just forward the call:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;close&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver.close()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can also hide the ugly &lt;code&gt;urllib.parse.urljoin(self.live_server_url)&lt;/code&gt; implementation detail:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;Browser&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; __init__(self, driver):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver = driver
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.live_server_url = &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;None&lt;/span&gt;  &lt;span style=&#34;color:#999;font-style:italic&#34;&gt;# will be set during test set up&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;get&lt;/span&gt;(self, url):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        full_url = urllib.parse.urljoin(self.live_server_url, url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.driver.get(full_url)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;TestPolls&lt;/span&gt;(LiveServerTestCase):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;setUp&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt;().setUp()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        driver = selenium.webdriver.Firefox()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.browser = Browser(driver)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.browser.live_server_url = self.live_server_url
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the test reads:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_home_no_polls&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.browser.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/polls&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        assert_no_polls(self.browser.page_source)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nice and short :)&lt;/p&gt;
&lt;h2 id=&#34;launching-the-driver-only-once&#34;&gt;Launching the driver only once&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#launching-the-driver-only-once&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;setUp()&lt;/code&gt; method is called before each test, so if we add more tests we&amp;rsquo;re going to create tons of instances of Firefox drivers.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s fix this by using &lt;code&gt;setUpClass&lt;/code&gt; (and not forgetting the &lt;code&gt;super()&lt;/code&gt; call)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;TestPolls&lt;/span&gt;(LiveServerTestCase):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@classmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;setUpClass&lt;/span&gt;(cls):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt;().setUpClass()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        driver = webdriver.Chrome()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cls.browser = Browser(driver)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;setUp&lt;/span&gt;(self):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.browser.base_url = self.live_server_url
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ffa500&#34;&gt;@classmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;tearDownClass&lt;/span&gt;(cls):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        cls.browser.close()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#24909d&#34;&gt;super&lt;/span&gt;().tearDownClass()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the &lt;code&gt;browser&lt;/code&gt; is a &lt;em&gt;class attribute&lt;/em&gt; instead of being an &lt;em&gt;instance attribute&lt;/em&gt;. So there&amp;rsquo;s only one &lt;code&gt;Browser&lt;/code&gt; object for the whole test suite, which is what we wanted.&lt;/p&gt;
&lt;p&gt;The rest of the code can still use &lt;code&gt;self.browser&lt;/code&gt;, though.&lt;/p&gt;
&lt;h2 id=&#34;debugging-tests&#34;&gt;Debugging tests&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#debugging-tests&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One last thing. You may think debugging such high-level tests would be painful.&lt;/p&gt;
&lt;p&gt;But it&amp;rsquo;s actually a pretty nice experience due to just one thing: the built-in Python debugger!&lt;/p&gt;
&lt;p&gt;Just add something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#447fcf&#34;&gt;test_login&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.browser.get(&lt;span style=&#34;color:#ed9d13&#34;&gt;&amp;#34;/login&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6ab825;font-weight:bold&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#447fcf;text-decoration:underline&#34;&gt;pdb&lt;/span&gt;; pdb.set_trace()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and then run the tests like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#aaa&#34;&gt;$&lt;/span&gt; pytest -k login -s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(The &lt;code&gt;-s&lt;/code&gt; is required to avoid capturing output, which &lt;code&gt;pdp&lt;/code&gt; does not like)&lt;/p&gt;
&lt;p&gt;And then, as soon as the tests reaches the line with &lt;code&gt;pdb.set_trace()&lt;/code&gt; you will have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A brand new Firefox instance running, with access to all the nice debugging tools (so you can quickly find out things like ids or CSS class names)&lt;/li&gt;
&lt;li&gt;&amp;hellip; and a nice REPL where you&amp;rsquo;ll be able to try out the code using &lt;code&gt;self.browser&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By the way, the REPL will be even nicer if you use &lt;a href=&#34;https://pypi.python.org/pypi/ipdb&#34;&gt;ipdb&lt;/a&gt; or &lt;a href=&#34;https://pypi.python.org/pypi/pdbpp/&#34;&gt;pdbpp&lt;/a&gt; and enjoy auto-completion and syntax coloring right from the REPL :)&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#conclusion&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;I hope I managed to show that you actually &lt;em&gt;can&lt;/em&gt; get creative writing tests, and even have some fun.&lt;/p&gt;
&lt;p&gt;See you next time!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Helping BBC subtitlers</title>
      <link>https://dmerej.info/blog/post/helping-bbc-subtitlers/</link>
      <pubDate>Sun, 18 Feb 2018 13:52:40 +0000</pubDate>
      
      <guid>https://dmerej.info/blog/post/helping-bbc-subtitlers/</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: this the first post in the &lt;a href=&#34;https://dmerej.info/blog/post/introducing-quantom-of-ideas/&#34;&gt;Quantum of Ideas&lt;/a&gt; series.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#introduction&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The other day I stumbled upon an article called &lt;a href=&#34;http://www.radiotimes.com/news/tv/2018-01-24/how-do-tv-subtitles-work/&#34;&gt;Why subtitlers have one of the hardest jobs in TV&lt;/a&gt;. Go read it now, I&amp;rsquo;ll wait.&lt;/p&gt;
&lt;p&gt;That got me thinking. What if there was a better way to transcribe what is said on TV into proper text, without having humans trying to repeat what they heard in a robotic voice, and then not-so-good &amp;ldquo;speech to text&amp;rdquo; programs converting robotic human voices to words?&lt;/p&gt;
&lt;h1 id=&#34;an-idea-using-old-tech&#34;&gt;An idea using old tech&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#an-idea-using-old-tech&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Turns out that writing text as fast as it is spoken is a very old problem. It&amp;rsquo;s called &lt;em&gt;stenography&lt;/em&gt; (or shorthand), and according to &lt;a href=&#34;https://en.wikipedia.org/wiki/Shorthand&#34;&gt;Wikipedia&lt;/a&gt;, it&amp;rsquo;s been around since classical antiquity.&lt;/p&gt;
&lt;p&gt;Heres&amp;rsquo;s what &lt;em&gt;stenography&lt;/em&gt; looks like using the French &amp;ldquo;Prévost-Delaunay&amp;rdquo; technique:
&lt;img src=&#34;https://dmerej.info/blog/pics/steno.png&#34; alt=&#34;stenograpy example&#34;&gt;&lt;/p&gt;
&lt;p&gt;In the same vein, converting human hand-writing to text is also a well-known problem. Just take a look at &lt;a href=&#34;https://en.wikipedia.org/wiki/Timeline_of_optical_character_recognition&#34;&gt;OCR history&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Speech recognition is quite new in comparison, and even if it has improved in the last decades, it&amp;rsquo;s still not entirely reliable, as the RadioTimes article shows.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s the idea:&lt;/p&gt;
&lt;p&gt;First, train people in stenography. In French, there used to be a job called &amp;ldquo;sténo-dactylo&amp;rdquo;, a secretary who used shorthand techniques to transcribe speech into an optimized hand-written notation, and then re-entered the text on a typing machine.&lt;/p&gt;
&lt;p&gt;To be trained in stenography can be useful in a bunch of situations. For instance, sometimes video or audio recording is prohibited by the law, and it&amp;rsquo;s up to a court clerk to transcribe everything that is said during a trial: see &lt;a href=&#34;https://www.youtube.com/watch?v=BxQMT4R51Dk&#34;&gt;this scene from &amp;ldquo;intolerable Cruelty&amp;rdquo;&lt;/a&gt; for an example.&lt;/p&gt;
&lt;p&gt;Note how the problem of punctuation goes away, because you can just &lt;em&gt;write&lt;/em&gt; &lt;code&gt;?&lt;/code&gt; instead of saying &amp;ldquo;question mark&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Also, the issue of coloring the subtitles with different colors depending on who&amp;rsquo;s speaking could be solved by inventing a notation, like prefixing the spoken words by the name of the speaker.&lt;/p&gt;
&lt;p&gt;Then, tweak an OCR Software so that it can work with the kind of input shown above. This may be a bit tricky because most of the time, the stenography techniques use a &amp;ldquo;phonetic&amp;rdquo; system, meaning that &amp;ldquo;eye&amp;rdquo; and &amp;ldquo;I&amp;rdquo; would both be written the same way. But I think we could train the software to automatically deduce the correct spelling.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s also the issue of proper nouns, but maybe we could fall back to regular writing for those.&lt;/p&gt;
&lt;p&gt;Looks to me this would cost less in R&amp;amp;D, and could also lead to a better quality of life for the subtitlers. No more sore face at the end of the day, and no more voice tics.&lt;/p&gt;
&lt;h1 id=&#34;an-even-simpler-idea&#34;&gt;An even simpler idea&amp;nbsp;&lt;a class=&#34;anchor&#34; href=&#34;#an-even-simpler-idea&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;While I was doing research for this article, I found that there&amp;rsquo;s also a job called STTR. The &amp;ldquo;Speech To Text Reporters&amp;rdquo; use a dedicated machine, as seen &lt;a href=&#34;https://www.youtube.com/watch?v=egLLsM9wN50&#34;&gt;on this demonstration video&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This seems to be already working just fine! Note how the names of the person speaking are handled, and how it&amp;rsquo;s a fully regulated profession. STTRs type &lt;strong&gt;at minimum&lt;/strong&gt; 180 words per minute and with 97% accuracy, and are tested in live situations.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a tiny issue because speech to text reporters have both their hands busy all the time, which means it would be hard for them to modify the position of the subtitles in real-time. But I believe the task of finding a &amp;rsquo;text-free&amp;rsquo; zone in the image and automatically move the subtitles could quite easily be done automatically by a small piece of software.&lt;/p&gt;
&lt;p&gt;So the question becomes: what was the reason for the BBC not to hire STTRs for the purpose of subtitling all their programs?&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have the answer, but if you ever need real-time speech to text conversion, please consider using a different technique than &amp;ldquo;respeaking&amp;rdquo;.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>
