<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog | Kelvin Wangonya</title><link>https://wangonya.com/blog/</link><description>Recent content in Blog on Kelvin Wangonya</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Fri, 08 May 2026 21:53:02 +0300</lastBuildDate><atom:link href="https://wangonya.com/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>We're here on Earth to fart around</title><link>https://wangonya.com/blog/here-on-earth-to-fart-around/</link><pubDate>Fri, 08 May 2026 21:53:02 +0300</pubDate><guid>https://wangonya.com/blog/here-on-earth-to-fart-around/</guid><description><![CDATA[<blockquote>
<p>DAVID BRANCACCIO: There&rsquo;s a little sweet moment, I&rsquo;ve got to say, in a very intense book– your latest– in which you&rsquo;re heading out the door and your wife says what are you doing? I think you say– I&rsquo;m getting– I&rsquo;m going to buy an envelope.</p>
<p>KURT VONNEGUT: Yeah.</p>
<p>DAVID BRANCACCIO: What happens then?</p>
<p>KURT VONNEGUT: Oh, she says well, you&rsquo;re not a poor man. You know, why don&rsquo;t you go online and buy a hundred envelopes and put them in the closet? And so I pretend not to hear her. And go out to get an envelope because I&rsquo;m going to have a hell of a good time in the process of buying one envelope. I meet a lot of people. And, see some great looking babes. And a fire engine goes by. And I give them the thumbs up. And, and ask a woman what kind of dog that is. And, and I don&rsquo;t know. The moral of the story is, is we&rsquo;re here on Earth to fart around. And, of course, the computers will do us out of that. And, what the computer people don&rsquo;t realize, or they don&rsquo;t care, is we&rsquo;re dancing animals. You know, we love to move around. And, we&rsquo;re not supposed to dance at all anymore.</p>
</blockquote>
<p><a href="https://crawshaw.io/blog/new-year">https://crawshaw.io/blog/new-year</a></p>
]]></description></item><item><title>An album for every year of my life</title><link>https://wangonya.com/blog/an-album-for-every-year-of-my-life/</link><pubDate>Wed, 15 Apr 2026 19:54:09 +0300</pubDate><guid>https://wangonya.com/blog/an-album-for-every-year-of-my-life/</guid><description><![CDATA[<p>Inspired by <a href="https://cafelog.fr/one-album-for-every-year-of-my-life/">Cafélog&rsquo;s post</a>, here&rsquo;s my list of favorite albums (one for every year since I was born, excluding the current year).</p>
<p>Good new music has a way of feeling like the best thing you&rsquo;ve ever heard, until the novelty wears off. I don&rsquo;t want to be updating this list every time that happens, so I&rsquo;ll only revisit it once a year.</p>
<table>
  <thead>
      <tr>
          <th>Year</th>
          <th>Cover Art</th>
          <th>Album</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1995</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/1995.webp" alt="">
</td>
          <td>Mobb Deep – The Infamous</td>
      </tr>
      <tr>
          <td>1996</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/1996.webp" alt="">
</td>
          <td>Fugees – The Score</td>
      </tr>
      <tr>
          <td>1997</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/1997.webp" alt="">
</td>
          <td>The Notorious B.I.G. – Life After Death</td>
      </tr>
      <tr>
          <td>1998</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/1998.webp" alt="">
</td>
          <td>OutKast – Aquemini</td>
      </tr>
      <tr>
          <td>1999</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/1999.webp" alt="">
</td>
          <td>Mos Def – Black On Both Sides</td>
      </tr>
      <tr>
          <td>2000</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2000.webp" alt="">
</td>
          <td>Common – Like Water For Chocolate</td>
      </tr>
      <tr>
          <td>2001</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2001.webp" alt="">
</td>
          <td>Kalamashaka – Ni Wakati</td>
      </tr>
      <tr>
          <td>2002</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2002.webp" alt="">
</td>
          <td>Clipse – Lord Willin'</td>
      </tr>
      <tr>
          <td>2003</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2003.webp" alt="">
</td>
          <td>Gang Starr – The Ownerz</td>
      </tr>
      <tr>
          <td>2004</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2004.webp" alt="">
</td>
          <td>Madvillain (MF DOOM &amp; Madlib) – Madvillainy</td>
      </tr>
      <tr>
          <td>2005</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2005.webp" alt="">
</td>
          <td>Kanye West – Late Registration</td>
      </tr>
      <tr>
          <td>2006</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2006.webp" alt="">
</td>
          <td>Ukoo Flani Mau Mau – Dandora Burning</td>
      </tr>
      <tr>
          <td>2007</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2007.webp" alt="">
</td>
          <td>Kanye West – Graduation</td>
      </tr>
      <tr>
          <td>2008</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2008.webp" alt="">
</td>
          <td>Fleet Foxes – Fleet Foxes</td>
      </tr>
      <tr>
          <td>2009</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2009.webp" alt="">
</td>
          <td>Mos Def – The Ecstatic</td>
      </tr>
      <tr>
          <td>2010</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2010.webp" alt="">
</td>
          <td>Big Boi – Sir Lucious Left Foot: The Son Of Chico Dusty</td>
      </tr>
      <tr>
          <td>2011</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2011.webp" alt="">
</td>
          <td>Kendrick Lamar – Section 80</td>
      </tr>
      <tr>
          <td>2012</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2012.webp" alt="">
</td>
          <td>Kendrick Lamar – Good Kid, M.A.A.D City</td>
      </tr>
      <tr>
          <td>2013</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2013.webp" alt="">
</td>
          <td>Intransit Riddim – Various Artists</td>
      </tr>
      <tr>
          <td>2014</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2014.webp" alt="">
</td>
          <td>J. Cole – 2014 Forest Hills Drive</td>
      </tr>
      <tr>
          <td>2015</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2015.webp" alt="">
</td>
          <td>Kendrick Lamar – To Pimp A Butterfly</td>
      </tr>
      <tr>
          <td>2016</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2016.webp" alt="">
</td>
          <td>Frank Ocean – Blonde</td>
      </tr>
      <tr>
          <td>2017</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2017.webp" alt="">
</td>
          <td>Kendrick Lamar – Damn</td>
      </tr>
      <tr>
          <td>2018</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2018.webp" alt="">
</td>
          <td>Mac Miller – Swimming</td>
      </tr>
      <tr>
          <td>2019</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2019.webp" alt="">
</td>
          <td>Common – Let Love</td>
      </tr>
      <tr>
          <td>2020</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2020.webp" alt="">
</td>
          <td>Armand Hammer – Shrines</td>
      </tr>
      <tr>
          <td>2021</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2021.webp" alt="">
</td>
          <td>Tyler, The Creator – Call Me If You Get Lost</td>
      </tr>
      <tr>
          <td>2022</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2022.webp" alt="">
</td>
          <td>Billy Woods – Aethiopes</td>
      </tr>
      <tr>
          <td>2023</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2023.webp" alt="">
</td>
          <td>Djungle &amp; Kitu Sewer – Kaunenge</td>
      </tr>
      <tr>
          <td>2024</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2024.webp" alt="">
</td>
          <td>Kitu Sewer – Makali Man</td>
      </tr>
      <tr>
          <td>2025</td>
          <td><img src="https://wangonya.com/blog/an-album-for-every-year-of-my-life/2025.webp" alt="">
</td>
          <td>Clipse – Let God Sort Em Out</td>
      </tr>
  </tbody>
</table>
]]></description></item><item><title>Handling missing dict keys, revisited</title><link>https://wangonya.com/blog/handling-missing-dict-keys-revisited/</link><pubDate>Wed, 08 Apr 2026 07:00:59 +0300</pubDate><guid>https://wangonya.com/blog/handling-missing-dict-keys-revisited/</guid><description><![CDATA[<p>A while back, I wrote a <a href="/blog/handling-missing-dict-keys/">post</a> showing how to handle missing dict keys. In summary:</p>
<ul>
<li>Using <code>setdefault</code></li>
<li>Using <code>defaultdict</code></li>
<li>Implementing <code>__missing__</code></li>
</ul>
<p>While the advice there still stands, I&rsquo;ve been reading through Fluent Python and came across two things worth being aware of when subclassing <code>dict</code>:</p>
<ol>
<li><code>__contains__</code> doesn&rsquo;t call <code>__missing__</code>, so <code>k in d</code> returns <code>False</code> for keys not yet set, even if <code>__missing__</code> would handle them</li>
<li><code>dict.get</code> doesn&rsquo;t call <code>__missing__</code>, so <code>.get(k)</code> won&rsquo;t use your custom default</li>
</ol>
<p>Both are by design and often what you want. <code>__missing__</code> is only used by <code>d[key]</code>, not other dict methods. Even <code>defaultdict</code> follows the same rule: only <code>d[key]</code> triggers the default factory and methods like <code>.get()</code> and <code>in</code> do not.</p>
<p>Overriding <code>get</code> is tempting but tricky. A naive implementation might look like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="font-weight:bold">class</span> <span style="font-weight:bold">M</span>(dict):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> __missing__(self, key):
</span></span><span style="display:flex;"><span>        value = <span style="font-style:italic">&#34;my default value&#34;</span>
</span></span><span style="display:flex;"><span>        self[key] = value
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> value
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> get(self, key, default=<span style="font-weight:bold">None</span>):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">try</span>:
</span></span><span style="display:flex;"><span>            <span style="font-weight:bold">return</span> self[key]  <span style="font-style:italic"># triggers __missing__ if key is absent</span>
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">except</span> <span style="font-weight:bold">KeyError</span>:
</span></span><span style="display:flex;"><span>            <span style="font-weight:bold">return</span> default    <span style="font-style:italic"># dead code, never reached</span>
</span></span></code></pre></div><p>This doesn&rsquo;t work. <code>self[key]</code> calls <code>__missing__</code> instead of raising <code>KeyError</code>, so the <code>except</code> block is unreachable and <code>default</code> is effectively useless:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; m = M()
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m.get(<span style="font-style:italic">&#34;x&#34;</span>, <span style="font-style:italic">&#34;fallback&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-style:italic">&#39;my default value&#39;</span>          <span style="font-style:italic"># expected &#34;fallback&#34;, got __missing__ value instead</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;x&#39;</span>: <span style="font-style:italic">&#39;my default value&#39;</span>}  <span style="font-style:italic"># side effect: key was set in the dict</span>
</span></span></code></pre></div><p>There&rsquo;s no clean way to honour both the <code>__missing__</code> default and the <code>default</code> parameter in <code>get</code>. It&rsquo;s better to accept that <code>get</code> and <code>__missing__</code> serve different purposes and leave <code>get</code> alone. Note that this applies to <code>dict</code> subclasses specifically. If you subclass <code>UserDict</code> instead, <code>get</code> calls <code>__getitem__</code> internally and <code>__missing__</code> is triggered. With a <code>dict</code> subclass, <code>get</code> is implemented in C and bypasses <code>__getitem__</code> altogether. The behaviour is inconsistent across the standard library depending on which base class you use.</p>
<p>As for <code>__contains__</code>, overriding it is a design decision. If your subclass provides a value for every possible key, returning <code>True</code> always can be reasonable:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="font-weight:bold">def</span> __contains__(self, key):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-weight:bold">True</span>
</span></span></code></pre></div><p>Only thing to keep in mind in this case is that <code>&quot;x&quot; in m</code> returns <code>True</code> even when <code>m</code> is <code>{}</code>, which looks confusing.</p>
]]></description></item><item><title>On Disabling Javascript</title><link>https://wangonya.com/blog/on-disabling-javascript/</link><pubDate>Fri, 24 Oct 2025 16:37:29 +0300</pubDate><guid>https://wangonya.com/blog/on-disabling-javascript/</guid><description><![CDATA[<blockquote>
<p>Update 2025-11-25: After trying this for about three weeks, I&rsquo;ve found that disabling Javascript by default is really inconvenient.
Many sites just don&rsquo;t work properly without it, and having to manually enable it every time is a hassle.
I guess that&rsquo;s the tradeoff one would have to make in this case, but I probably just don&rsquo;t care enough at the moment
to go ahead with this. Of course I might revisit this again later, but for now it&rsquo;s back to the default browsing experience.</p>
</blockquote>
<p>This is something I always knew you could do but never considered doing - until I came across <a href="https://%E3%83%9E%E3%83%AA%E3%82%A6%E3%82%B9.com/">this site</a>.
I was browsing some pages on that site, and had to leave to check something else on a different tab.
After a while, I noticed something weird with the tabs:
<img src="https://wangonya.com/blog/on-disabling-javascript/tabs.png" alt="tabs">
</p>
<p>I&rsquo;m pretty sure I didn&rsquo;t search for &ldquo;censorship on hackernews&rdquo;, or &ldquo;how to hack coworkers phone&rdquo;.
And I&rsquo;m certainly not asking ChatGPT for pickup line suggestions 😂. What was going on?</p>
<p>Well, Javascript.</p>
<p><img src="https://wangonya.com/blog/on-disabling-javascript/message.png" alt="message">
</p>
<p>That message is shown when you go back to the tabs. Basically, the site uses Javascript to change the page title when the tab is not in focus.</p>
<p>This is not actually the first time I&rsquo;ve seen this. The same thing happens on <a href="https://sizeof.cat/">sizeof.cat</a>,
but there it&rsquo;s done just for fun. That&rsquo;s why I never thought twice about it when I first saw it there.
The author of マリウス also <a href="https://%E3%83%9E%E3%83%AA%E3%82%A6%E3%82%B9.com/updates-2025-q3/#site-updates">acknowledges</a> that he got the idea from the same source:</p>
<blockquote>
<p>I got the inspiration for this from this post by sizeof.cat, [&hellip;].</p>
<p>While sizeof.cat uses this feature purely for the lulz, I believe it can serve as an effective way to encourage people to disable JavaScript in their browsers by default, and to be very selective about which websites they enable it for.</p>
</blockquote>
<p>I think the fact that he decided to use this trick for this purpose is genius. Props to him. It&rsquo;s really effective.</p>
<p>Most of these titles are not too bad (though they would still raise eyebrows), but some would be quite embarrassing if seen in your tabs by others.</p>
<p><img src="https://wangonya.com/blog/on-disabling-javascript/js.png" alt="js">
</p>
<p>How do you explain to someone that the &ldquo;jeff bezos nudes&rdquo; tab they saw in the background wasn&rsquo;t actually a Google search for &ldquo;jeff bezos nudes&rdquo;,
but a joke from some blog on the internet?</p>
<p>I&rsquo;m sure there are some security features on browsers to restrict the harm JS can do on your machine - but the fact that something like this can happen behind your back really makes you think.</p>
<p>Of course it&rsquo;s going to be a pain to turn off JS by default and manually enable it whenever I visit a site I need and find that it just won&rsquo;t work unless I have it enabled. But I&rsquo;ll try it out for a while and see how it goes.</p>
<p>Side note: I also learned about <a href="https://en.wikipedia.org/wiki/Punycode">Punycode</a> on that site, so - worth the visit.</p>
]]></description></item><item><title>Handling NULL values for "not equal" checks in SQL</title><link>https://wangonya.com/blog/mysql-where-not-equal-null/</link><pubDate>Mon, 19 May 2025 11:08:03 +0300</pubDate><guid>https://wangonya.com/blog/mysql-where-not-equal-null/</guid><description><![CDATA[<p>This one bit me today. Apparently <code>NULL</code> values give unexpected results when checked using <code>!=</code> or <code>&lt;&gt;</code>.</p>
<p>For example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>id | model     | competitor_type
</span></span><span style="display:flex;"><span><span style="font-style:italic">--------------------------------
</span></span></span><span style="display:flex;"><span>1  | Ariya     | <span style="font-weight:bold">NULL</span>
</span></span><span style="display:flex;"><span>2  | Frontier  | <span style="font-weight:bold">NULL</span>
</span></span><span style="display:flex;"><span>3  | Rogue     | Competitor
</span></span><span style="display:flex;"><span>4  | Sentra    | Non-competitor
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">SELECT</span> * <span style="font-weight:bold">FROM</span> <span style="font-weight:bold">table</span> <span style="font-weight:bold">WHERE</span> <span style="font-weight:bold">LOWER</span>(competitor_type) != <span style="font-style:italic">&#34;non-competitor&#34;</span>;
</span></span></code></pre></div><p>I expected to see ids 1, 2 and 3 as a result, but only got 3.</p>
<p>This makes sense when you think about it because comparisons can&rsquo;t be carried out against unavailable values. So if <code>NULL</code> values are expected in the result, they should explicitly be included in the query.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="font-weight:bold">SELECT</span> * <span style="font-weight:bold">FROM</span> <span style="font-weight:bold">table</span> <span style="font-weight:bold">WHERE</span> (<span style="font-weight:bold">LOWER</span>(competitor_type) != <span style="font-style:italic">&#34;non-competitor&#34;</span> <span style="font-weight:bold">OR</span> competitor_type <span style="font-weight:bold">IS</span> <span style="font-weight:bold">NULL</span>);
</span></span></code></pre></div><p>This can also be handled by using <code>COALESCE</code> to get values from <code>NULL</code>, or by using the NULL-safe equal <code>&lt;=&gt;</code>, but I think it&rsquo;s a lot more clear to just check for <code>NULL</code> explicitly.</p>
]]></description></item><item><title>Be careful with join type typos</title><link>https://wangonya.com/blog/join-typo/</link><pubDate>Thu, 07 Nov 2024 09:00:30 +0300</pubDate><guid>https://wangonya.com/blog/join-typo/</guid><description><![CDATA[<p>I noticed a typo in one of my sql queries today, but the funny thing is the query still worked fine.
It looked something like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="font-weight:bold">SELECT</span>
</span></span><span style="display:flex;"><span>    *
</span></span><span style="display:flex;"><span><span style="font-weight:bold">FROM</span>
</span></span><span style="display:flex;"><span>    table_1
</span></span><span style="display:flex; background-color:#e5e5e5"><span>LEFFT <span style="font-weight:bold">JOIN</span>
</span></span><span style="display:flex;"><span>    table_2
</span></span><span style="display:flex;"><span><span style="font-weight:bold">USING</span> (a,b);
</span></span></code></pre></div><p>At first I thought BigQuery was pretty smart and just assumed I meant <code>LEFT</code> instead.
Maybe it&rsquo;s a common typo and there&rsquo;s an alias for it. So I got curious and tried out this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;display:grid;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="font-weight:bold">SELECT</span>
</span></span><span style="display:flex;"><span>    *
</span></span><span style="display:flex;"><span><span style="font-weight:bold">FROM</span>
</span></span><span style="display:flex;"><span>    table_1
</span></span><span style="display:flex; background-color:#e5e5e5"><span>LEFFFFTFT <span style="font-weight:bold">JOIN</span>
</span></span><span style="display:flex;"><span>    table_2
</span></span><span style="display:flex;"><span><span style="font-weight:bold">USING</span> (a,b);
</span></span></code></pre></div><p>No error. That can&rsquo;t be right.</p>
<p>That&rsquo;s when it hit me. This query isn&rsquo;t doing a <code>LEFT JOIN</code>. It&rsquo;s using the incorrectly spelled
name as an alias for <code>table_1</code> and doing an <code>INNER JOIN</code> instead. Basically this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="font-weight:bold">SELECT</span>
</span></span><span style="display:flex;"><span>    *
</span></span><span style="display:flex;"><span><span style="font-weight:bold">FROM</span>
</span></span><span style="display:flex;"><span>    table_1 <span style="font-weight:bold">AS</span> LEFFT
</span></span><span style="display:flex;"><span><span style="font-weight:bold">JOIN</span>
</span></span><span style="display:flex;"><span>    table_2
</span></span><span style="display:flex;"><span><span style="font-weight:bold">ON</span> LEFFT.a = table_2.a <span style="font-weight:bold">AND</span> LEFFT.b = table_2.b
</span></span></code></pre></div><p>So the query works fine but the results would be incorrect.</p>
<p>This is one benefit of syntax highlighting I&rsquo;ve never really thought about until now. The only reason I noticed this quickly was by
seeing <code>LEFFT</code> wasn&rsquo;t highlighted as I expected. The results of the query looked fine at first glance so this would have definitely bitten
me somewhere down the line if it got to production.</p>
]]></description></item><item><title>with statements don't create scope</title><link>https://wangonya.com/blog/with-scope/</link><pubDate>Tue, 01 Oct 2024 16:27:39 +0300</pubDate><guid>https://wangonya.com/blog/with-scope/</guid><description><![CDATA[<p>I saw some code today that initialized a variable inside <code>with</code> and continued to use it outside the block.
I&rsquo;ve always assumed <code>with</code> statements had their own scope so this had me a little confused. Turns out this is perfectly fine.</p>
<blockquote>
</blockquote>
<blockquote>
<p>A <code>with</code> statement does not create a scope (like <code>if</code>, <code>for</code> and <code>while</code> do not create a scope either).</p>
<p>As a result, Python will analyze the code and see that you made an assignment in the <code>with</code> statement, and thus that will make the variable local (to the real scope).</p>
<p>In Python variables do not need initialization in all code paths: as a programmer, you are responsible to make sure that a variable is assigned before it is used. This can result in shorter code: say for instance you know for sure that a list contains at least one element, then you can assign in a <code>for</code> loop. In Java assignment in a <code>for</code> loop is not considered safe (since it is possible that the body of the loop is never executed).</p>
<p>Initialization before the <code>with</code> scope can be safer in the sense that after the <code>with</code> statement we can safely assume that the variable exists. If on the other hand the variable should be assigned in the <code>with</code> statement, not initializing it before the <code>with</code> statement actually results in an additional check: Python will error if somehow the assignment was skipped in the <code>with</code> statement.</p>
<p>A <code>with</code> statement is only used for context management purposes. It forces (by syntax) that the context you open in the <code>with</code> is closed at the end of the indentation.</p>
<p><a href="https://stackoverflow.com/a/45100308/9312256">source</a></p>
</blockquote>
]]></description></item><item><title>Spotify Cleaner</title><link>https://wangonya.com/blog/spotify-cleaner/</link><pubDate>Wed, 25 Sep 2024 08:09:31 +0300</pubDate><guid>https://wangonya.com/blog/spotify-cleaner/</guid><description><![CDATA[<p>I&rsquo;ve had my Spotify account for a long time, and over that time, my musical tastes have evolved.
As a consequence, there are a lot of liked songs, playlists, and podcasts I no longer listen to but have in my library.
There&rsquo;s nothing wrong with keeping them in the library—I don&rsquo;t have them downloaded, so they&rsquo;re not really taking up any space—but I don&rsquo;t like the clutter.</p>
<p>As far as I know, Spotify doesn&rsquo;t provide any way to batch delete things, so I created a <a href="https://github.com/wangonya/spotify-cleaner">spotify-cleaner</a> for this.</p>
<p><img src="https://wangonya.com/blog/spotify-cleaner/Screenshot.png" alt="screenshot">
</p>
<p>I used it to delete everything (all liked songs, albums, podcasts, and playlists), but it can also delete just a few selected items.</p>
<p>If this is something you feel might also be useful to you, check the <a href="https://github.com/wangonya/spotify-cleaner">repo</a> for instructions on how to use it.</p>
]]></description></item><item><title>man pages have sections!</title><link>https://wangonya.com/blog/man-pages-sections/</link><pubDate>Wed, 25 Sep 2024 05:47:44 +0300</pubDate><guid>https://wangonya.com/blog/man-pages-sections/</guid><description><![CDATA[<p>I noticed this when reading through <a href="https://beej.us/guide/bgc/html/split/index.html">Beej&rsquo;s Guide to C Programming</a>. While explaining <code>printf</code>, reference is made to <code>man 3 printf</code> - which looked different from how I usually run <code>man</code>. Why the <code>3</code>?</p>
<p>So I ran <code>man printf</code> instead. Output:</p>
<pre tabindex="0"><code>PRINTF(1)                                       User Commands                                       PRINTF(1)

NAME
       printf - format and print data
 ...
</code></pre><p>Then <code>man 3 printf</code>:</p>
<pre tabindex="0"><code>printf(3)                                  Library Functions Manual                                 printf(3)

NAME
       printf,  fprintf,  dprintf, sprintf, snprintf, vprintf, vfprintf, vdprintf, vsprintf, vsnprintf - for‐
       matted output conversion

LIBRARY
       Standard C library (libc, -lc)

SYNOPSIS
       #include &lt;stdio.h&gt;
...
</code></pre><p>And I noticed what I&rsquo;d been missing. The first output has <code>User Commands</code> at the top, while the other one has <code>Library Functions Manual</code>.</p>
<p>As it turns out, man pages are divided into sections. I&rsquo;ve never thought to check <code>man man</code>, but it explains this.</p>
<pre tabindex="0"><code>MAN(1)                                        Manual pager utils                                       MAN(1)

NAME
       man - an interface to the system reference manuals

SYNOPSIS
       man [man options] [[section] page ...] ...

...

A manual page consists of several sections.

A section, if provided, will direct man to look only in that section of the manual.
The default action is to search in all of the available sections following a
pre-defined  order (see DEFAULTS), and to show only the first page found,
even if page exists in several sections.

    The table below shows the section numbers of the manual followed by the types of pages they contain.

    1   Executable programs or shell commands
    2   System calls (functions provided by the kernel)
    3   Library calls (functions within program libraries)
    4   Special files (usually found in /dev)
    5   File formats and conventions, e.g. /etc/passwd
    6   Games
    7   Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7), man-pages(7)
    8   System administration commands (usually only for root)
    9   Kernel routines [Non standard]
</code></pre><p>To check what sections are available for a command:</p>
<pre tabindex="0"><code>man -f &lt;command&gt;

# for example:
man -f printf
printf (1)           - format and print data
printf (1p)          - write formatted output
printf (3)           - formatted output conversion
printf (3p)          - print formatted output
</code></pre><p>You may need to run <code>sudo mandb</code> if you get the error <code>nothing appropriate</code> with the above command.</p>
]]></description></item><item><title>Learning touch typing</title><link>https://wangonya.com/blog/learning-touch-typing/</link><pubDate>Tue, 27 Aug 2024 06:22:21 +0300</pubDate><guid>https://wangonya.com/blog/learning-touch-typing/</guid><description><![CDATA[<p>I now understand why I&rsquo;ve always had a hard time getting into Vim.
I&rsquo;ve tried it on and off for years, and of everything I&rsquo;ve read about it, I have not seen &lsquo;knowing to type properly&rsquo;
as a prerequisite. I think it is. &lsquo;Keeping your fingers on the home row&rsquo; is a big thing with it,
but this doesn&rsquo;t help if you&rsquo;re not usually typing with your fingers on the home row in the first place.</p>
<p>Anyway, Vim aside, I&rsquo;ve decided to learn how to type properly. I can type pretty fast, but I only ever use my index and middle fingers.
I also have to look at the keys when typing. I think this really limits my speed.
And not just my typing speed - the speed of all my work in general.
The fact that I have to look down to type, then up to confirm that what I&rsquo;ve written is correct means I&rsquo;m using twice the time to write -
and I do this a lot in the course of a normal working day.</p>
<p>Something else that really bugs me is when I&rsquo;ve typed a whole sentence only to look up and realize
the window/textbox I was supposed to be typing on is no longer in focus, and all my typing wasn&rsquo;t
doing anything, or worse, was triggering random shortcuts in a different window.</p>
<p><a href="https://www.keybr.com/">keybr</a> has been awesome for practicing.
I also try to practice opportunistically while working, which has made me very slow, but I think it&rsquo;s a worthwhile investment.</p>
]]></description></item><item><title>On embracing asynchronous communication</title><link>https://wangonya.com/blog/async-communication/</link><pubDate>Wed, 27 Mar 2024 12:12:34 +0300</pubDate><guid>https://wangonya.com/blog/async-communication/</guid><description><![CDATA[<p>I&rsquo;ve been trying to improve my workflows this year. One thing I&rsquo;ve known for a while, but never really got
serious about implementing, is defaulting to asynchronous communication. I first learned about this concept
a few years ago when reading <a href="https://basecamp.com/handbook/how-we-work#asynchronously">Basecamp&rsquo;s Employee Handbook</a>.</p>
<p>I work remotely for a company in the UK, and we use Slack for communication. The timezone difference is only
two/three hours, so the whole team is usually all online at the same time for most of the day. I (and I&rsquo;m sure most other
members of the team) just find it a lot easier to pull someone in for a &lsquo;quick&rsquo; huddle each time there&rsquo;s something
to discuss. I always hesitate before doing this, but end up doing it anyway most of the time. The fact that it is
very easy to do doesn&rsquo;t help. I think it does more harm than good.</p>
<p>More than a few times I try to invite someone for a huddle, and they&rsquo;re not available. I then have to write down
whatever I wanted us to discuss - and it always ends up feeling more productive. I think better when I write. Or,
maybe writing actually forces me to think about the thing more - something I may have been avoiding and choosing
the easier option of &lsquo;discussing&rsquo; it instead. I even come up with the solution sometimes in the middle of writing,
and find the call, or even the message itself, not to be necessary.</p>
<p>Another benefit of writing things down is that you can actually refer back to the messages months/years down the
line when you can&rsquo;t figure out why a certain decision was made. I know Slack huddles have threads attached to
them but we rarely ever use them. Handovers are a lot easier when you can actually search for something in threads
and follow discussions that were made in the past.</p>
<p>Writing is also great practice for communication skills as things usually need to be a lot more clear written down than spoken.</p>
<p>I know these kinds of impromptu calls are distracting, but I understand why people do them. It&rsquo;s just the
easiest thing to do in the moment. They&rsquo;re hardly ever necessary though.</p>
<p>In my experience, I have never been in a situation where I would be completely blocked unless I got into a call
to discuss something. I&rsquo;m never in need of an immediate answer to be able to continue with my work. And even if
I am, there&rsquo;s no guarantee that calling someone is going to get me that answer. They may not be available, and then
I&rsquo;ll still have to write down whatever I wanted anyway.</p>
<p>It&rsquo;s usually not worth breaking someone&rsquo;s focus over whatever issue I feel needs immediate attention. It&rsquo;s not easy,
but it&rsquo;s worth embracing asynchronous communication more.</p>
<p>Write something down as clearly and precisely as you can and send it.
Don&rsquo;t expect an immediate reply. Find something else to do in the meantime.</p>
<p>I think that&rsquo;s a better way to work.</p>
<h2 id="update-2024-09-25">Update (2024-09-25)</h2>
<p>Found this link that I think supplements this post well:
<a href="https://switowski.com/blog/no-hello-no-quick-call-no-agendaless-meetings/">No &ldquo;Hello&rdquo;, No &ldquo;Quick Call&rdquo;, and no Meetings Without an Agenda</a></p>
]]></description></item><item><title>Pydantic validators don't raise validation errors immediately</title><link>https://wangonya.com/blog/pydantic-validators-raise/</link><pubDate>Wed, 06 Mar 2024 05:15:40 +0300</pubDate><guid>https://wangonya.com/blog/pydantic-validators-raise/</guid><description><![CDATA[<p>This one really had me confused. I was facing an error with <a href="https://docs.pydantic.dev/latest/concepts/validators/">Pydantic validators</a> which I thought I had handled, but it just didn&rsquo;t work as expected.</p>
<p>The schema looked something like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="font-weight:bold">class</span> <span style="font-weight:bold">Schema</span>(BaseModel):
</span></span><span style="display:flex;"><span>    dates: List[str]
</span></span><span style="display:flex;"><span>    start_date: Optional[str]
</span></span><span style="display:flex;"><span>    end_date: Optional[str]
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    @validator(<span style="font-style:italic">&#34;dates&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> update_date_format(cls, v):
</span></span><span style="display:flex;"><span>        ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    @validator(<span style="font-style:italic">&#34;start_date&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> set_start_date(cls, v, values):
</span></span><span style="display:flex;"><span>        <span style="font-style:italic"># some logic here that expects `dates` to exist</span>
</span></span><span style="display:flex;"><span>        v = values[<span style="font-style:italic">&#39;dates&#39;</span>][0]
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> v
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    @validator(<span style="font-style:italic">&#34;end_date&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> set_end_date(cls, v, values):
</span></span><span style="display:flex;"><span>        <span style="font-style:italic"># some logic here that expects `dates` to exist</span>
</span></span><span style="display:flex;"><span>        v = values[<span style="font-style:italic">&#39;dates&#39;</span>][-1]
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> v
</span></span></code></pre></div><p>My assumption in the last two validators was that <code>dates</code> would always be available because it&rsquo;s a required field.
To my surprise, an <code>IndexError</code> was always raised on <code>set_start_date</code>.</p>
<p>So I thought, ok, I&rsquo;ll raise a <code>ValueError</code> myself on <code>update_date_format</code> since the required field check doesn&rsquo;t seem to be working.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="font-weight:bold">class</span> <span style="font-weight:bold">Schema</span>(BaseModel):
</span></span><span style="display:flex;"><span>    dates: List[str]
</span></span><span style="display:flex;"><span>    start_date: Optional[str]
</span></span><span style="display:flex;"><span>    end_date: Optional[str]
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    @validator(<span style="font-style:italic">&#34;dates&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> update_date_format(cls, v):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> v:
</span></span><span style="display:flex;"><span>            <span style="font-weight:bold">raise</span> <span style="font-weight:bold">ValueError</span>(<span style="font-style:italic">&#34;dates is a required field&#34;</span>)
</span></span><span style="display:flex;"><span>        ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    @validator(<span style="font-style:italic">&#34;start_date&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> set_start_date(cls, v, values):
</span></span><span style="display:flex;"><span>        <span style="font-style:italic"># some logic here that expects `dates` to exist</span>
</span></span><span style="display:flex;"><span>        v = values[<span style="font-style:italic">&#39;dates&#39;</span>][0]
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> v
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    @validator(<span style="font-style:italic">&#34;end_date&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">def</span> set_end_date(cls, v, values):
</span></span><span style="display:flex;"><span>        <span style="font-style:italic"># some logic here that expects `dates` to exist</span>
</span></span><span style="display:flex;"><span>        v = values[<span style="font-style:italic">&#39;dates&#39;</span>][-1]
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> v
</span></span></code></pre></div><p>Again, an <code>IndexError</code> was raised on <code>set_start_date</code>. It&rsquo;s like my check on <code>update_date_format</code> was completely ignored.
I even put a breakpoint on the line to make sure it was being hit. It was.</p>
<p>So, validation errrors aren&rsquo;t raised immediately. They&rsquo;re collected and returned all at once in the response.</p>
<p>Despite seeing this countless times in <code>422</code> responses, I had never thought about it. It made perfect sense.
You don&rsquo;t want to return one error at a time as an API response. It&rsquo;s much better to return a response detailing everything that&rsquo;s wrong with the payload.</p>
<p>From the <a href="https://docs.pydantic.dev/latest/errors/errors/">docs</a>:</p>
<blockquote>
<p>One exception will be raised regardless of the number of errors found, that <code>ValidationError</code> will contain information about all the errors and how they happened.</p>
</blockquote>
<p>The important thing to remember is that this only happens for validation errors (i.e errors raised through <code>ValueError</code> or <code>AssertionError</code>).
This is why the <code>IndexError</code> was always raised immediately it happened.</p>
<h2 id="how-to-stop-validation-on-the-first-error">How to stop validation on the first error</h2>
<p>According to <a href="https://stackoverflow.com/a/69538066/9312256">this answer</a>:</p>
<blockquote>
<p>If you have checks, the failure of which should interrupt the further validation, then put them in the <code>pre=True</code> root validator. Because field validation will not occur if <code>pre=True</code> root validators raise an error.</p>
<p>For example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-py" data-lang="py"><span style="display:flex;"><span><span style="font-weight:bold">class</span> <span style="font-weight:bold">PayloadValidator</span>(BaseModel):
</span></span><span style="display:flex;"><span>   emailId: List[str]
</span></span><span style="display:flex;"><span>   role: str
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>   @root_validator(pre=<span style="font-weight:bold">True</span>)
</span></span><span style="display:flex;"><span>   <span style="font-weight:bold">def</span> root_validate(cls, values):
</span></span><span style="display:flex;"><span>       <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> values[<span style="font-style:italic">&#39;emailId&#39;</span>]:
</span></span><span style="display:flex;"><span>           <span style="font-weight:bold">raise</span> <span style="font-weight:bold">ValueError</span>(<span style="font-style:italic">&#34;Email list is empty.&#34;</span>)
</span></span><span style="display:flex;"><span>       <span style="font-weight:bold">return</span> values
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>   @validator(<span style="font-style:italic">&#34;emailId&#34;</span>)
</span></span><span style="display:flex;"><span>   <span style="font-weight:bold">def</span> valid_domains(cls, emailId):
</span></span><span style="display:flex;"><span>       <span style="font-weight:bold">return</span> emailId
</span></span></code></pre></div></blockquote>
]]></description></item><item><title>Trying out Ubuntu 23.04</title><link>https://wangonya.com/blog/ubuntu-23-04/</link><pubDate>Thu, 07 Sep 2023 05:34:19 +0300</pubDate><guid>https://wangonya.com/blog/ubuntu-23-04/</guid><description><![CDATA[<p>I haven&rsquo;t used Ubuntu since I first discovered Linux 9 years ago in University, so I thought I&rsquo;d give it a try this past weekend.
I didn&rsquo;t like it. I only used it for a day and a half before I had to wipe everything and go back to Manjaro.</p>
<p>Before I get into the things that really bothered me, here&rsquo;s what I liked:</p>
<h2 id="1-online-accounts">1. Online accounts</h2>
<p>This is more of a Gnome thing than Ubuntu, but still, I love that I can add all my online accounts in the settings and have everything synced up automatically in the calendar and email apps.
I love KDE Plasma, but this is the one thing I really miss in it.</p>
<p>I actually don&rsquo;t care much for email, but calendar notifications is something I really need. I always find myself forgetting about scheduled meetings.
Of course I could find another way to deal with this, but it would be really nice if I could have it OOTB with my distro.</p>
<h2 id="2-wallpapers">2. Wallpapers</h2>
<p>Not really a major thing but Ubuntu and ElementaryOS are the two distros I&rsquo;ve seen that always have the best wallpapers shipped by default.</p>
<h2 id="3-somewhat-consistent-themeing">3. Somewhat consistent themeing</h2>
<p>I think Ubuntu does this really well with the Yaru theme. I say somewhat because this is Gnome, and there are always <a href="#3-themeing-is-such-a-pain">issues</a> with themeing Gnome.</p>
<p>That&rsquo;s about it for what I liked.</p>
<p>Here&rsquo;s what I didn&rsquo;t like:</p>
<h2 id="1-installer-didnt-work">1. Installer didn&rsquo;t work</h2>
<p>This is a big problem. Ubuntu released a new installer written in flutter and it just didn&rsquo;t work for me.</p>
<p>It kept crashing in the middle of the setup process (before I actually got to the final install step), and when I finally got to the final step and clicked install, it froze at 5%.</p>
<p>I tried multiple times and even downloaded an update for the installer. Same thing.</p>
<p>Finally, I decided to go back to the website and download the legacy installer version - which worked fine.</p>
<p>This should have been a huge red flag for me. I should have given up on the whole thing the moment I had issues with the installer. But oh well, I apparently had time to waste.</p>
<p>This was a bad one.</p>
<p>Everything else after this is based on personal preference so not anything really wrong with Ubuntu itself.</p>
<h2 id="2-huge-window-title-bars">2. Huge window title bars</h2>
<p>I think the window title bars on Gnome are ridiculously huge. I can&rsquo;t stand them.
I tried getting around that with a theme that offers a &ldquo;compact&rdquo; version, but -</p>
<h2 id="3-themeing-is-such-a-pain">3. Themeing is such a pain</h2>
<p>Why do I need to install an extra piece of software (Tweaks) to be able to change the default system font?
I don&rsquo;t understand the reasoning behind this. At the very least, this should be an option in the settings.</p>
<p>Fonts aside, applying a new shell theme doesn&rsquo;t really change the theme for all apps.
Something to do with &ldquo;Libadwaita&rdquo; and legacy apps. I didn&rsquo;t look into it enough to figure out what was going on.
But apps like the terminal and the file manager just didn&rsquo;t want to be themed differently.
I use these apps a lot so it would be too distracting for me to have them not looking the same as everything else.</p>
<h2 id="4-different-ways-to-install-software">4. Different ways to install software</h2>
<p>This is totally me having been spoiled by the conveniences of the <a href="https://aur.archlinux.org/">AUR</a>.
When I install an arch based distro, I have a script that installs <a href="https://github.com/Jguer/yay">yay</a>, and uses it to install everything else from wherever it&rsquo;s available (official repos or AUR).</p>
<p><code>yay -S literally-anything</code>. It Just Works ™.</p>
<p>With Ubuntu, I have to figure out if the thing is in the repos. I may have to add some new repos, add GPG keys and run system updates.
Maybe the thing is a snap. In that case, I need to run some different commands to install snaps.</p>
<p>I wasn&rsquo;t even able to install previous versions of Python <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. Something about it being a security issue for non-lts versions (can&rsquo;t remember the exact error).</p>
<p>There&rsquo;s probably something out there like yay but for Ubuntu - I don&rsquo;t know. But as it is, it&rsquo;s all just too much work.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Yes, I should have used pyenv instead.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description></item><item><title>Python __slots__</title><link>https://wangonya.com/blog/python-slots/</link><pubDate>Tue, 15 Aug 2023 22:03:09 +0300</pubDate><guid>https://wangonya.com/blog/python-slots/</guid><description><![CDATA[<p>I just learned about this today while going through the <a href="https://github.com/dabeaz-course/python-mastery">python mastery</a> course.
Apparently, some good memory optimization can be done by using it in classes.</p>
<p><a href="https://stackoverflow.com/a/28059785/9312256">This answer</a> does a good job explaining how it works.</p>
<p>I&rsquo;ve not had a need for it yet, but it&rsquo;s a good thing to keep in mind for when I do end up needing it.</p>
]]></description></item><item><title>Incron</title><link>https://wangonya.com/blog/incron/</link><pubDate>Wed, 12 Jul 2023 08:58:30 +0300</pubDate><guid>https://wangonya.com/blog/incron/</guid><description><![CDATA[<blockquote>
<p><a href="http://inotify.aiken.cz/?section=incron&amp;page=about&amp;lang=en">incron</a> is an &ldquo;inotify cron&rdquo; system. It consists of a daemon and a table manipulator. You can use it a similar way as the regular cron. The difference is that the inotify cron handles filesystem events rather than time periods.</p>
</blockquote>
<p>I use it to auto-commit changes made to specific files to version control.</p>
<h2 id="example-usage">Example usage</h2>
<p>View incrontabs:</p>
<pre tabindex="0"><code>incrontab -l
</code></pre><p>Add/edit incrontabs:</p>
<pre tabindex="0"><code>incrontab -e
</code></pre><pre tabindex="0"><code># commit and push when file is modified and saved
/home/wangonya/dir_to_track	IN_MODIFY	cd /home/wangonya/dir_to_track; git commit -a -m &#39;autocommit on change&#39;; git push
</code></pre><p><a href="https://wiki.archlinux.org/title/Incron">Archwiki</a> for more info.</p>
]]></description></item><item><title>Taking notes</title><link>https://wangonya.com/blog/notes/</link><pubDate>Fri, 23 Jun 2023 18:26:44 +0300</pubDate><guid>https://wangonya.com/blog/notes/</guid><description><![CDATA[<p>I need to get in the habit of taking notes while I work. Especially when I&rsquo;m debugging.
I&rsquo;ve noticed a poor habit recur when I&rsquo;m working on a particularly difficult problem.</p>
<p>It usually goes something like this:</p>
<ul>
<li>Start working on problem. Do some research. Try out <code>A</code>.</li>
<li><code>A</code> doesn&rsquo;t work. Do some more research. Try <code>B</code>.</li>
<li><code>B</code> doesn&rsquo;t work.</li>
<li>Try <code>C</code>. Nothing.</li>
<li>At this point I&rsquo;m already tired so I think to myself, &ldquo;<code>A</code> seems like a pretty good idea. Why didn&rsquo;t it work? Let&rsquo;s try it again.&rdquo;.</li>
<li>Oh, that&rsquo;s why <code>A</code> didn&rsquo;t work. Of course.</li>
<li>Try some variation of <code>B</code>.</li>
<li>Try <code>C</code> again.</li>
<li>Think about <code>A</code> some more&hellip;</li>
</ul>
<p>So much time is wasted, with very little progress made. Even worse, if this is at the end of the day and I have to leave it pending and come back to it the next day - or if I have to stash the changes and work on something else for a while then come back to it later, then the cycle begins all over again.</p>
<p>If notes are taken at each step of the way, it&rsquo;s clear what works and what doesn&rsquo;t - and why. This isn&rsquo;t just helpful in the moment. Chances are I&rsquo;ll come across a similar issue in the future. I can&rsquo;t always rely on memory on these things. Experience has shown it to be very unreliable.</p>
<p>As much as I plan to mostly use pen and paper for this, it should also give me ample opportunity to blog more. Many problems should be general enough for someone<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> else out there to benefit from.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Barely anyone reads my blog, I know — but it should at least act as a backup to my pen and paper.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description></item><item><title>Adding anything to i3blocks</title><link>https://wangonya.com/blog/i3blocks/</link><pubDate>Wed, 14 Jun 2023 21:34:04 +0300</pubDate><guid>https://wangonya.com/blog/i3blocks/</guid><description><![CDATA[<style>
  img {width: 60%}
</style>
<p>This was initially a post about adding what&rsquo;s playing on Spotify to <a href="https://github.com/vivien/i3blocks">i3blocks</a>. I had just started using i3blocks then and thought it was pretty cool how easy it was to do.
I&rsquo;ve since discovered the possibilities are endless. You can add pretty much anything that outputs text to the statusbar.</p>
<p>Below are some examples of what&rsquo;s possible.</p>
<h2 id="showing-and-controlling-music">Showing and controlling music</h2>
<p>I like seeing what&rsquo;s playing without having to bring up the Spotify app every time. If I can also control playback without bringing up the app, even better.</p>
<p>By default, i3 comes with <a href="https://i3wm.org/i3bar/">i3bar</a>. I&rsquo;m sure I could achieve the same thing on i3bar <a href="https://i3wm.org/docs/i3status.html#_external_scripts_programs_with_i3status">with enough time and effort</a>, but its just much easier to do it with i3blocks.</p>
<p>Info on what&rsquo;s playing can be gotten using <a href="https://github.com/altdesktop/playerctl">playerctl</a> or <a href="https://github.com/pwittchen/spotify-cli-linux">spotify-cli-linux</a>.</p>
<p>Then add the command to the i3blocks config:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="font-weight:bold">[spotify]</span>
</span></span><span style="display:flex;"><span>command=<span style="font-style:italic">spotifycli --status</span>
</span></span><span style="display:flex;"><span>color=<span style="font-style:italic">#00FFB3</span>
</span></span><span style="display:flex;"><span>interval=<span style="font-style:italic">2</span>
</span></span></code></pre></div><p><img src="https://wangonya.com/blog/i3blocks/1.png" alt="screenshot_1">
</p>
<p>I&rsquo;ve opted to create a separate script file so I can handle mouse clicks.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="">#!/usr/bin/env bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># i3blocks spotify script</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>spotifycli --status
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">case</span> $BLOCK_BUTTON in
</span></span><span style="display:flex;"><span>  1) spotifycli --prev ;;  <span style="font-style:italic"># left click, previous</span>
</span></span><span style="display:flex;"><span>  2) spotifycli --playpause ;; <span style="font-style:italic"># middle click, play/pause</span>
</span></span><span style="display:flex;"><span>  3) spotifycli --next ;; <span style="font-style:italic"># right click, next</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">esac</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="font-style:italic">; i3blocks config</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">[spotify-playback-status]</span>
</span></span><span style="display:flex;"><span>command=<span style="font-style:italic">spotifycli --playbackstatus</span>
</span></span><span style="display:flex;"><span>color=<span style="font-style:italic">#00FFB3</span>
</span></span><span style="display:flex;"><span>interval=<span style="font-style:italic">2</span>
</span></span><span style="display:flex;"><span>separator=<span style="font-style:italic">false</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">[spotify]</span>
</span></span><span style="display:flex;"><span>command=<span style="font-style:italic">~/.config/i3blocks/scripts/spotify</span>
</span></span><span style="display:flex;"><span>color=<span style="font-style:italic">#00FFB3</span>
</span></span><span style="display:flex;"><span>interval=<span style="font-style:italic">2</span>
</span></span></code></pre></div><p><img src="https://wangonya.com/blog/i3blocks/2.png" alt="screenshot_2">

<img src="https://wangonya.com/blog/i3blocks/3.png" alt="screenshot_3">
</p>
<p>I also tried this on Strawberry player using playerctl and it worked just as well.</p>
<p><img src="https://wangonya.com/blog/i3blocks/4.png" alt="screenshot_4">
</p>
<h2 id="showing-wakatime-stats">Showing <a href="https://wakatime.com/">Wakatime</a> stats</h2>
<p>Using <a href="https://github.com/wakatime/wakatime-cli">wakatime-cli</a>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="font-style:italic">; i3blocks config</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">[wakatime]</span>
</span></span><span style="display:flex;"><span>label=<span style="font-style:italic"></span>
</span></span><span style="display:flex;"><span>command=<span style="font-style:italic">wakatime-cli --today</span>
</span></span><span style="display:flex;"><span>color=<span style="font-style:italic">#3daee9</span>
</span></span><span style="display:flex;"><span>interval=<span style="font-style:italic">300</span>
</span></span></code></pre></div><p><img src="https://wangonya.com/blog/i3blocks/5.png" alt="screenshot_5">
</p>
]]></description></item><item><title>mysql-dump specific tables</title><link>https://wangonya.com/blog/mysql-dump-specific-tables/</link><pubDate>Sat, 13 Aug 2022 15:19:50 +0300</pubDate><guid>https://wangonya.com/blog/mysql-dump-specific-tables/</guid><description><![CDATA[<p>If you only need to dump one table:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mysqldump -u username -ppassword db_name table_name &gt; dump.sql
</span></span></code></pre></div><p>For multiple tables, separate the table names with a whitespace:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mysqldump -u username -ppassword db_name table_name_1 table_name_2 &gt; dump.sql
</span></span></code></pre></div><p>To only get tables with a certain prefix, e.g <code>pref_</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mysqldump db_name <span style="font-weight:bold">$(</span>mysql -D db_name -Bse <span style="font-style:italic">&#34;show tables like &#39;pref\_%&#39;&#34;</span><span style="font-weight:bold">)</span> &gt; dump.sql
</span></span><span style="display:flex;"><span><span style="font-style:italic"># flags: -B batch, -s silent mode, -e execute</span>
</span></span></code></pre></div><p>To only dump rows that meet a specific criteria:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mysqldump -u username -ppassword db_name table_name --where=<span style="font-style:italic">&#34;where clause here&#34;</span> &gt; dump.sql
</span></span></code></pre></div><p>Importing the dump file:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mysql -u username -ppassword db_name &lt; dump.sql
</span></span></code></pre></div>]]></description></item><item><title>Grokking algorithms notes</title><link>https://wangonya.com/blog/grokking-algorithms-notes/</link><pubDate>Sat, 21 May 2022 12:03:23 +0300</pubDate><guid>https://wangonya.com/blog/grokking-algorithms-notes/</guid><description><![CDATA[<p>Book: <a href="https://www.manning.com/books/grokking-algorithms">https://www.manning.com/books/grokking-algorithms</a></p>
<h2 id="the-feynman-algorithm">The Feynman algorithm</h2>
<ol>
<li>Write down the problem.</li>
<li>Think real hard.</li>
<li>Write down the solution.</li>
</ol>
<h2 id="binary-search">Binary search</h2>
<p>Use if the input is sorted.</p>
<p>If the input consists of numbers, for example, half the numbers are eliminated in each step with binary search. When searching for a number between 1 and 100, a maximum of 7 steps are needed to get the result.</p>
<pre tabindex="0"><code>100 -&gt; 50 -&gt; 25 -&gt; 13 -&gt; 7 -&gt; 4 -&gt; 2 -&gt; 1
</code></pre><p>In general, for any list of <em>n</em>, binary search will take log<sub>2</sub><em>n</em> steps to run in the worst case.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> binary_search(_list, item):
</span></span><span style="display:flex;"><span>    high = len(_list) - 1
</span></span><span style="display:flex;"><span>    low = 0
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">while</span> high &gt;= low:
</span></span><span style="display:flex;"><span>        mid = (high + low) // 2
</span></span><span style="display:flex;"><span>        guess = _list[mid]
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">if</span> guess == item:
</span></span><span style="display:flex;"><span>            <span style="font-weight:bold">return</span> mid
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">elif</span> guess &gt; item:
</span></span><span style="display:flex;"><span>            high = mid - 1
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>            low = mid + 1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-weight:bold">None</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> __name__ == <span style="font-style:italic">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>    position = binary_search([2, 3, 5, 7, 8, 9, 12, 24, 32], 12)
</span></span><span style="display:flex;"><span>    print(position)
</span></span></code></pre></div><h2 id="arrays--linked-lists">Arrays &amp; linked lists</h2>
<h3 id="arrays">Arrays</h3>
<blockquote>
<p>Random access. Fast reads, slow writes.</p>
</blockquote>
<p>With arrays, data is stored contiguously (right next to each other) in memory. If more data needs to be added and there&rsquo;s not enough space for it to be stored contiguously in the current location, everything needs to be moved to a different location that will allow this to be done. Inserting data into the middle of an array also requires moving everything else to the right to make space for the new item. Adding data can therefore be quite slow. While it&rsquo;s possible to reserve slots as a workaround for having to change locations, the reserved slots end up being wasted in case they&rsquo;re not used. Deleting is also slow as everything needs to be moved up to fill the empty space (assuming the deletion was done in the middle).</p>
<h3 id="linked-lists">Linked lists</h3>
<blockquote>
<p>Sequential access. Fast writes, slow reads.</p>
</blockquote>
<p>Data can be saved anywhere in memory. Each item stores the address of the next item in the list. This solves the problem of needing to store everything together, but is slow when reading data. To read the last item in the list, all previous items will have to be accessed. Adding and deleting is fast as it only requires a change in the next address pointed to.</p>
<h2 id="recursion">Recursion</h2>
<blockquote>
<p>Loops may achieve a performance gain for your program. Recursion may achieve a performance gain for your programmer. Choose which is more important in your situation! - <a href="https://stackoverflow.com/a/72694/9312256">https://stackoverflow.com/a/72694/9312256</a></p>
</blockquote>
<p>Every recursive function has two parts: the base case, and the recursive case.</p>
<blockquote>
<p><strong>Tip</strong> 💡</p>
<p>When you’re writing a recursive function involving an array, the base case is often an empty array or an array with one element.</p>
</blockquote>
<blockquote>
<p><strong>Exercise</strong></p>
<p>Find the total of a list of numbers using recursion.</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> _sum(_list):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> _list:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> 0
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> len(_list) == 1:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> _list[0]
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> _list.pop() + _sum(_list)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(_sum([1,2,3,4,5])) <span style="font-style:italic"># =&gt; 15</span>
</span></span><span style="display:flex;"><span>print(_sum([2,4,6])) <span style="font-style:italic"># =&gt; 12</span>
</span></span></code></pre></div><h3 id="the-stack">The stack</h3>
<p>Items are added at the top (push) and removed from the top (pop). FILO.</p>
<h4 id="the-call-stack-with-recursion">The call stack with recursion</h4>
<p>Example using factorial calculation:</p>
<p>Code:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> fact(x):
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">if</span> x == 1:
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> 1
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> x * fact(x-1)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>fact(3)
</span></span></code></pre></div><p>Call stack:</p>
<table>
  <thead>
      <tr>
          <th>Code</th>
          <th>Call stack</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>fact(3)</td>
          <td><strong>fact(x=3)</strong></td>
      </tr>
      <tr>
          <td>if x == 1:</td>
          <td><strong>fact(x=3)</strong></td>
      </tr>
      <tr>
          <td>else:</td>
          <td><strong>fact(x=3)</strong></td>
      </tr>
      <tr>
          <td>return x * fact(x-1)</td>
          <td><strong>fact(x=2)</strong><br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>if x == 1:</td>
          <td><strong>fact(x=2)</strong><br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>else:</td>
          <td><strong>fact(x=2)</strong><br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>return x * fact(x-1)</td>
          <td><strong>fact(x=1)</strong><br/>fact(x=2)<br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>if x == 1:</td>
          <td><strong>fact(x=1)</strong><br/>fact(x=2)<br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>return 1</td>
          <td><strong>fact(x=1)</strong> &lt;= popped off the stack<br/>fact(x=2)<br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>return x * fact(x-1)</td>
          <td><strong>fact(x=2)</strong> &lt;= popped off the stack<br/>fact(x=3)</td>
      </tr>
      <tr>
          <td>return x * fact(x-1)</td>
          <td><strong>fact(x=3)</strong> &lt;= popped off the stack</td>
      </tr>
  </tbody>
</table>
<p>Each call to <code>fact</code> has its own copy of <code>x</code>. You can’t access a different function’s copy of <code>x</code>.</p>
<h2 id="divide--conquer">Divide &amp; conquer</h2>
<p>D&amp;C algorithms are recursive algorithms.</p>
<p>To solve a problem using D&amp;C, there are two steps:</p>
<ol>
<li>Figure out the base case. This should be the simplest possible case.</li>
<li>Divide or decrease your problem until it becomes the base case.</li>
</ol>
<blockquote>
<p><strong>Exercise</strong></p>
<p>Suppose you’re a farmer with a plot of land - 1680 * 640 meters. You want to divide this farm evenly into square plots. You want the plots to be as big as possible. How do you figure out the largest square size you can use for a plot of land?</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> divide_land(a, b):
</span></span><span style="display:flex;"><span>    bigger_side = max(a,b)
</span></span><span style="display:flex;"><span>    smaller_side = min(a,b)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> smaller_side * 2 == bigger_side:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> (smaller_side, smaller_side)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        rem = bigger_side % smaller_side
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> divide_land(rem, smaller_side)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(divide_land(1680, 640)) <span style="font-style:italic"># =&gt; (80, 80)</span>
</span></span><span style="display:flex;"><span>print(divide_land(400, 640)) <span style="font-style:italic"># =&gt; (80, 80)</span>
</span></span></code></pre></div><h2 id="quicksort">Quicksort</h2>
<p>Uses divide &amp; conquer.</p>
<h3 id="sorting-an-array-of-numbers-with-quick-sort">Sorting an array of numbers with quick sort</h3>
<p>Base case: empty array or array with one element.</p>
<p>For bigger arrays, choose an element from the array (pivot) and find elements smaller than the pivot and larger than it. All smaller elements go to the left of the pivot. Bigger elements go to the right of the pivot. Recurse until array is sorted.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> quicksort(array):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> len(array) &lt; 2:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> array
</span></span><span style="display:flex;"><span>    pivot = array[0]
</span></span><span style="display:flex;"><span>    less = [i <span style="font-weight:bold">for</span> i <span style="font-weight:bold">in</span> array[1:] <span style="font-weight:bold">if</span> i &lt; pivot]
</span></span><span style="display:flex;"><span>    equal = [i <span style="font-weight:bold">for</span> i <span style="font-weight:bold">in</span> array[1:] <span style="font-weight:bold">if</span> i == pivot]
</span></span><span style="display:flex;"><span>    greater = [i <span style="font-weight:bold">for</span> i <span style="font-weight:bold">in</span> array[1:] <span style="font-weight:bold">if</span> i &gt; pivot]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> quicksort(less) + equal + [pivot] + quicksort(greater)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(quicksort([10, 2, 3, 7, 12, 2, 5, 1, 3])) <span style="font-style:italic"># =&gt; [1, 2, 2, 3, 3, 5, 7, 10, 12]</span>
</span></span></code></pre></div><p>The performance of quicksort heavily depends on the pivot choosen. If the first element is the pivot and quicksort is called with an array that is already sorted it doesn’t check to see whether the input array is already sorted. So it will still try to sort it.</p>
<p>Middle pivots work better. In the worst case (first item as pivot), the stack size is O(<em>n</em>). In the best case (middle pivot), the stack size is O(log <em>n</em>).</p>
<p>The overall complexity of quicksort is O(<em>n</em> log <em>n</em>)</p>
<h2 id="graphs">Graphs</h2>
<p>A graph models a set of connections / how different things are connected to one another. It&rsquo;s made up of nodes and edges. A node can be directly connected to many other nodes. Those nodes are called its neighbors.</p>
<h3 id="breadth-first-search">Breadth-first search</h3>
<p>Used to find the shortest path to a target. It can help answer two types of questions:</p>
<ul>
<li>Is there a path from node A to node B?</li>
<li>What is the shortest path from node A to node B?</li>
</ul>
<blockquote>
<p><strong>Example</strong></p>
<p>Suppose you’re the proud owner of a mango farm. You’re looking for a mango seller who can sell your mangoes. Are you connected to a mango seller on Facebook? Well, you can search through your friends.</p>
<p>First, make a list of friends to search. Now, go to each person in the list and check whether that person sells mangoes. Suppose none of your friends are mango sellers. Now you have to search through your friends’ friends. Each time you search for someone from the list, add all of their friends to the list. This way, you not only search your friends, but you search their friends too.</p>
<p>First should be searched first before friends of friends. To keep this order, you need a queue.</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">collections</span> <span style="font-weight:bold">import</span> deque
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>graph = dict()
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;you&#34;</span>] = [<span style="font-style:italic">&#34;alice&#34;</span>, <span style="font-style:italic">&#34;bob&#34;</span>, <span style="font-style:italic">&#34;claire&#34;</span>]
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;bob&#34;</span>] = [<span style="font-style:italic">&#34;anuj&#34;</span>, <span style="font-style:italic">&#34;peggy&#34;</span>]
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;alice&#34;</span>] = [<span style="font-style:italic">&#34;peggy&#34;</span>]
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;claire&#34;</span>] = [<span style="font-style:italic">&#34;tom mango seller&#34;</span>, <span style="font-style:italic">&#34;jonny&#34;</span>]
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;anuj&#34;</span>] = []
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;peggy&#34;</span>] = []
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;tom mango seller&#34;</span>] = []
</span></span><span style="display:flex;"><span>graph[<span style="font-style:italic">&#34;jonny&#34;</span>] = []
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> search(name):
</span></span><span style="display:flex;"><span>    search_queue = deque()
</span></span><span style="display:flex;"><span>    search_queue += graph[name]
</span></span><span style="display:flex;"><span>    searched = []
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">while</span> search_queue:
</span></span><span style="display:flex;"><span>        person = search_queue.popleft()
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> person <span style="font-weight:bold">in</span> searched:
</span></span><span style="display:flex;"><span>            <span style="font-weight:bold">if</span> <span style="font-style:italic">&#34;mango seller&#34;</span> <span style="font-weight:bold">in</span> person:
</span></span><span style="display:flex;"><span>                <span style="font-weight:bold">return</span> person
</span></span><span style="display:flex;"><span>            <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>                search_queue += graph[person]
</span></span><span style="display:flex;"><span>                searched.append(person)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-weight:bold">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(search(<span style="font-style:italic">&#34;you&#34;</span>)) <span style="font-style:italic"># =&gt; tom mango seller</span>
</span></span></code></pre></div><p>Running time: O(V+E) (V for number of vertices, E for number of edges).</p>
<blockquote>
<p><strong>Tip</strong> 💡</p>
<p>If you have a problem like “find the shortest X,” try modeling your problem as a graph and use breadth-first search to solve.</p>
</blockquote>
<h3 id="dijkstras-algorithm">Dijkstra’s algorithm</h3>
<p>BFS gets the shortest path to a target, in terms of number of nodes that have to be accessed before reaching the target. Dijkstra&rsquo;s algorithm gets the <strong>fastest</strong> path to a target, even though the path may not necessarily be the shortest.</p>
<p>To calculate the shortest path in an unweighted graph, use breadth-first search. To calculate the shortest path in a weighted graph, use Dijkstra’s algorithm.</p>
<p>Steps:</p>
<ol>
<li>Find the “cheapest” node. This is the node that can be accessed in the least amount of time.</li>
<li>Update the costs of the neighbors of this node.</li>
<li>Repeat until this has been done for every node in the graph.</li>
<li>Calculate the final path.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># TODO: implementation</span>
</span></span></code></pre></div><blockquote>
<p><strong>Note</strong> 🐛</p>
<p>You can’t use Dijkstra’s algorithm if you have negative-weight edges as they break the algorithm.</p>
<p>For a graph with negative-weight edges, use <em><a href="https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm">Bellman-Ford algorithm</a></em>.</p>
</blockquote>
<h2 id="greedy-algorithms">Greedy algorithms</h2>
<p>A greedy algorithm is simple: at each step, pick the optimal move. In technical terms: at each step, pick the locally optimal solution, and in the end you’re left with the globally optimal solution. It doesn&rsquo;t always get the most optimal solution, but it comes close enough.</p>
<h2 id="dynamic-programming">Dynamic programming</h2>
<p>Dynamic programming starts by solving subproblems and builds up to solving the big problem.</p>
<p>Useful when trying to optimize something given a constraint.</p>
]]></description></item><item><title>Checking string contains substring</title><link>https://wangonya.com/blog/check-string-substring-go/</link><pubDate>Fri, 29 Apr 2022 11:02:01 +0300</pubDate><guid>https://wangonya.com/blog/check-string-substring-go/</guid><description><![CDATA[<p>From <a href="https://stackoverflow.com/a/61842548/9312256">this answer</a>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="font-weight:bold">import</span> (
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;regexp&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;strings&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> (
</span></span><span style="display:flex;"><span>    str    = <span style="font-style:italic">&#34;something&#34;</span>
</span></span><span style="display:flex;"><span>    substr = <span style="font-style:italic">&#34;some&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// 1. Contains</span>
</span></span><span style="display:flex;"><span>res := strings.Contains(str, substr)
</span></span><span style="display:flex;"><span>fmt.Println(res) <span style="font-style:italic">// true</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// 2. Index: check the index of the first instance of substr in str, or -1 if substr is not present</span>
</span></span><span style="display:flex;"><span>i := strings.Index(str, substr)
</span></span><span style="display:flex;"><span>fmt.Println(i) <span style="font-style:italic">// 0</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// 3. Split by substr and check len of the slice, or length is 1 if substr is not present</span>
</span></span><span style="display:flex;"><span>ss := strings.Split(str, substr)
</span></span><span style="display:flex;"><span>fmt.Println(len(ss)) <span style="font-style:italic">// 2</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// 4. Check number of non-overlapping instances of substr in str</span>
</span></span><span style="display:flex;"><span>c := strings.Count(str, substr)
</span></span><span style="display:flex;"><span>fmt.Println(c) <span style="font-style:italic">// 1</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// 5. RegExp</span>
</span></span><span style="display:flex;"><span>matched, _ := regexp.MatchString(substr, str)
</span></span><span style="display:flex;"><span>fmt.Println(matched) <span style="font-style:italic">// true</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// 6. Compiled RegExp</span>
</span></span><span style="display:flex;"><span>re = regexp.MustCompile(substr)
</span></span><span style="display:flex;"><span>res = re.MatchString(str)
</span></span><span style="display:flex;"><span>fmt.Println(res) <span style="font-style:italic">// true</span>
</span></span></code></pre></div><p>Option two easily solves <a href="https://leetcode.com/problems/implement-strstr/">this
problem</a>.</p>
]]></description></item><item><title>Handling missing dict keys</title><link>https://wangonya.com/blog/handling-missing-dict-keys/</link><pubDate>Thu, 10 Feb 2022 06:10:15 +0300</pubDate><guid>https://wangonya.com/blog/handling-missing-dict-keys/</guid><description><![CDATA[<p>Trying to access a non-existent key using this notation:
<code>dict[key]</code> raises a <code>KeyError</code>. An easy
workaround for this is to use <code>get(key)</code> instead, which
returns <code>None</code> if <code>key</code> isn&rsquo;t found, or
<code>get(key, default)</code> which returns <code>default</code> if
<code>key</code> isn&rsquo;t found.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; d = {}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d
</span></span><span style="display:flex;"><span>{}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d[<span style="font-style:italic">&#34;x&#34;</span>]
</span></span><span style="display:flex;"><span>Traceback (most recent call last):
</span></span><span style="display:flex;"><span>  File <span style="font-style:italic">&#34;&lt;stdin&gt;&#34;</span>, line 1, in &lt;module&gt;
</span></span><span style="display:flex;"><span>KeyError: <span style="font-style:italic">&#39;x&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d.get(<span style="font-style:italic">&#34;x&#34;</span>)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d
</span></span><span style="display:flex;"><span>{}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d.get(<span style="font-style:italic">&#34;x&#34;</span>,<span style="font-style:italic">&#34;y&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-style:italic">&#39;y&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d
</span></span><span style="display:flex;"><span>{}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span></code></pre></div><p>But what if you want to not only return a default if the key is missing,
but also assign that default to the specified key in the dict? There are
a couple of ways to do that.</p>
<h2 id="1-setdefault">1. <code>setdefault</code></h2>
<blockquote>
<p><code>setdefault(key[, default])</code></p>
<p>If key is in the dictionary, return its value. If not, insert key with
a value of default and return default. <code>default</code> defaults
to <code>None</code>.</p>
<p><a href="https://docs.python.org/3/library/stdtypes.html#dict.setdefault">docs</a></p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; d
</span></span><span style="display:flex;"><span>{}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d.setdefault(<span style="font-style:italic">&#34;x&#34;</span>,<span style="font-style:italic">&#34;y&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-style:italic">&#39;y&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; d
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;x&#39;</span>: <span style="font-style:italic">&#39;y&#39;</span>}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span></code></pre></div><h2 id="2-defaultdict">2. <code>defaultdict</code></h2>
<blockquote>
<p><code>class collections.defaultdict(default_factory=None, /[, ...])</code></p>
<p>The first argument provides the initial value for the
<a href="https://docs.python.org/3/library/collections.html#collections.defaultdict.default_factory">default factory</a>
attribute; it defaults to <code>None</code>. All remaining arguments
are treated the same as if they were passed to the
<a href="https://docs.python.org/3/library/stdtypes.html#dict">dict</a>
constructor, including keyword arguments.</p>
<p><a href="https://docs.python.org/3/library/collections.html#collections.defaultdict">docs</a></p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; from collections import defaultdict
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; i = defaultdict(int)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; i
</span></span><span style="display:flex;"><span>defaultdict(&lt;class <span style="font-style:italic">&#39;int&#39;</span>&gt;, {})
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; i[<span style="font-style:italic">&#34;x&#34;</span>]
</span></span><span style="display:flex;"><span>0
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; i
</span></span><span style="display:flex;"><span>defaultdict(&lt;class <span style="font-style:italic">&#39;int&#39;</span>&gt;, {<span style="font-style:italic">&#39;x&#39;</span>: 0})
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; i[<span style="font-style:italic">&#34;y&#34;</span>]
</span></span><span style="display:flex;"><span>0
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; i
</span></span><span style="display:flex;"><span>defaultdict(&lt;class <span style="font-style:italic">&#39;int&#39;</span>&gt;, {<span style="font-style:italic">&#39;x&#39;</span>: 0, <span style="font-style:italic">&#39;y&#39;</span>: 0})
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span></code></pre></div><p>Note that no <code>KeyError</code> is raised despite the key not
existing at first. Instead, the key is created with the default value of
the type passed into <code>defaultdict</code>, in this case
<code>0</code> for <code>int</code>. If we used <code>list</code>
instead, the default value would be <code>[]</code>, and so on.</p>
<p>Further reading:</p>
<ul>
<li><a href="https://docs.python.org/3/library/collections.html#defaultdict-examples">defaultdict examples</a></li>
<li><a href="https://stackoverflow.com/questions/3483520/use-cases-for-the-setdefault-dict-method">Use cases for the &lsquo;setdefault&rsquo; dict method</a>
(vs defaultdict)</li>
</ul>
<h2 id="3-implement-__missing__">3. Implement <code>__missing__</code></h2>
<p>This is actually what <code>defaultdict</code> does behind the scenes.
Use this when <code>defaultdict</code> doesn&rsquo;t fit your usecase.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; class M(dict):
</span></span><span style="display:flex;"><span>...     def __missing__(self, key):
</span></span><span style="display:flex;"><span>...             value = <span style="font-style:italic">&#34;my default value&#34;</span>
</span></span><span style="display:flex;"><span>...             self[key] = value
</span></span><span style="display:flex;"><span>...             <span style="font-weight:bold">return</span> value
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m = M()
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m
</span></span><span style="display:flex;"><span>{}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m[<span style="font-style:italic">&#34;x&#34;</span>]
</span></span><span style="display:flex;"><span><span style="font-style:italic">&#39;my default value&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;x&#39;</span>: <span style="font-style:italic">&#39;my default value&#39;</span>}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m[<span style="font-style:italic">&#34;y&#34;</span>]
</span></span><span style="display:flex;"><span><span style="font-style:italic">&#39;my default value&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; m
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;x&#39;</span>: <span style="font-style:italic">&#39;my default value&#39;</span>, <span style="font-style:italic">&#39;y&#39;</span>: <span style="font-style:italic">&#39;my default value&#39;</span>}
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span></code></pre></div>]]></description></item><item><title>Kadane's algorithm</title><link>https://wangonya.com/blog/kadanes-algorithm/</link><pubDate>Thu, 02 Dec 2021 08:25:49 +0300</pubDate><guid>https://wangonya.com/blog/kadanes-algorithm/</guid><description><![CDATA[<p>Possible use case: <a href="https://en.wikipedia.org/wiki/Maximum_subarray_problem">Maximum subarray
problem</a>.</p>
<h2 id="steps">Steps</h2>
<ol>
<li>Initialize two variables: <code>max_sum = current_sum = 0</code></li>
<li>Loop through numbers in list
<ul>
<li>Set <code>current_sum = max(0, current_sum + list[i])</code></li>
<li>Set <code>max_sum = max(max_sum, current_sum)</code></li>
</ul>
</li>
<li>Return <code>max_sum</code></li>
</ol>
<h2 id="caveats-">Caveats <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></h2>
<ul>
<li>Kadane&rsquo;s Algorithm requires at least one positive number, so an
input of all negative numbers would be invalid.</li>
<li>If the array contains all non-negative numbers, then the problem is
trivial; a maximum subarray is the entire array.</li>
<li>If the array contains all non-positive numbers, then a solution is
any subarray of size 1 containing the maximal value of the array (or
the empty subarray (which has sum 0), if it is permitted).</li>
<li>Several different sub-arrays may have the same maximum sum.</li>
</ul>
<h3 id="solving-best-time-to-buy-and-sell-stock-with-kadanes-algorithm">Solving <a href="https://leetcode.com/problems/best-time-to-buy-and-sell-stock/">Best Time to Buy and Sell Stock</a> with Kadane&rsquo;s Algorithm</h3>
<p>Slightly tweak the algorithm to track max profit and min price.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> maxProfit(self, prices: List[int]) -&gt; int:
</span></span><span style="display:flex;"><span>    max_profit, min_price = 0, float(<span style="font-style:italic">&#34;inf&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">for</span> price <span style="font-weight:bold">in</span> prices:
</span></span><span style="display:flex;"><span>        min_price = min(min_price, price)
</span></span><span style="display:flex;"><span>        max_profit = max(max_profit, price - min_price)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> max_profit
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://en.wikipedia.org/wiki/Maximum_subarray_problem">Wikipedia: Maximum subarray
problem</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://stackoverflow.com/questions/9942228/kadane-algorithm-negative-numbers">SO: Kadane Algorithm Negative
Numbers</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></description></item><item><title>Running multiple programs in parallel from a bash script</title><link>https://wangonya.com/blog/running-bash-parallel/</link><pubDate>Mon, 22 Nov 2021 06:58:33 +0300</pubDate><guid>https://wangonya.com/blog/running-bash-parallel/</guid><description><![CDATA[<p>This comes in handy when I want to, for example:</p>
<ul>
<li>run a MySQL proxy to Cloudql or similar, then</li>
<li>run a project server (fastapi, django etc) that depends on the
database connection</li>
</ul>
<p>From <a href="https://stackoverflow.com/questions/3004811/how-do-you-run-multiple-programs-in-parallel-from-a-bash-script">this
answer</a>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>set -m  <span style="font-style:italic"># enable job control</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>prog1 &amp; prog2 &amp;&amp; fg
</span></span></code></pre></div><p>This will:</p>
<ul>
<li>Start prog1.</li>
<li>Send it to background, but keep printing its output.</li>
<li>Start prog2, and keep it in foreground, so you can close it with
ctrl-c.</li>
<li>When you close prog2, you&rsquo;ll return to prog1&rsquo;s foreground, so you
can also close it with ctrl-c.</li>
</ul>
]]></description></item><item><title>Processing iterators in parallel</title><link>https://wangonya.com/blog/python-zip/</link><pubDate>Wed, 03 Nov 2021 06:13:46 +0300</pubDate><guid>https://wangonya.com/blog/python-zip/</guid><description><![CDATA[<p>Use <a href="https://docs.python.org/3/library/functions.html#zip">zip</a></p>
<blockquote>
<p><code>zip(*iterables, strict=False)</code></p>
<p>Iterate over several iterables in parallel, producing tuples with an
item from each one.</p>
</blockquote>
<h2 id="examples">Examples</h2>
<h3 id="without-zip">Without zip</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>countries = [<span style="font-style:italic">&#34;Kenya&#34;</span>, <span style="font-style:italic">&#34;Tanzania&#34;</span>, <span style="font-style:italic">&#34;Uganda&#34;</span>]
</span></span><span style="display:flex;"><span>capitals = [<span style="font-style:italic">&#34;Nairobi&#34;</span>, <span style="font-style:italic">&#34;Dodoma&#34;</span>, <span style="font-style:italic">&#34;Kampala&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="font-style:italic">&#34;=== using range ===&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> i <span style="font-weight:bold">in</span> range(len(countries)):
</span></span><span style="display:flex;"><span>    country, capital = countries[i], capitals[i]
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">f</span><span style="font-style:italic">&#34;Country: </span><span style="font-weight:bold;font-style:italic">{</span>country<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">, Capital: </span><span style="font-weight:bold;font-style:italic">{</span>capital<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(<span style="font-style:italic">&#34;=== using enumerate ===&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> i, country <span style="font-weight:bold">in</span> enumerate(countries):
</span></span><span style="display:flex;"><span>    country, capital = countries[i], capitals[i]
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">f</span><span style="font-style:italic">&#34;Country: </span><span style="font-weight:bold;font-style:italic">{</span>country<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">, Capital: </span><span style="font-weight:bold;font-style:italic">{</span>capital<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#34;</span>)
</span></span></code></pre></div><p>Output:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>=== using range ===
</span></span><span style="display:flex;"><span>Country: Kenya, Capital: Nairobi
</span></span><span style="display:flex;"><span>Country: Tanzania, Capital: Dodoma
</span></span><span style="display:flex;"><span>Country: Uganda, Capital: Kampala
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>=== using enumerate ===
</span></span><span style="display:flex;"><span>Country: Kenya, Capital: Nairobi
</span></span><span style="display:flex;"><span>Country: Tanzania, Capital: Dodoma
</span></span><span style="display:flex;"><span>Country: Uganda, Capital: Kampala
</span></span></code></pre></div><h3 id="with-zip">With zip</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>print(<span style="font-style:italic">&#34;=== using zip ===&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> country, capital <span style="font-weight:bold">in</span> zip(countries, capitals):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">f</span><span style="font-style:italic">&#34;Country: </span><span style="font-weight:bold;font-style:italic">{</span>country<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">, Capital: </span><span style="font-weight:bold;font-style:italic">{</span>capital<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#34;</span>)
</span></span></code></pre></div><p>Output:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>=== using zip ===
</span></span><span style="display:flex;"><span>Country: Kenya, Capital: Nairobi
</span></span><span style="display:flex;"><span>Country: Tanzania, Capital: Dodoma
</span></span><span style="display:flex;"><span>Country: Uganda, Capital: Kampala
</span></span></code></pre></div><p>Same result, but more elegant.</p>
]]></description></item><item><title>Getting the Python version at runtime</title><link>https://wangonya.com/blog/python-runtime-version/</link><pubDate>Sun, 24 Oct 2021 17:42:19 +0300</pubDate><guid>https://wangonya.com/blog/python-runtime-version/</guid><description><![CDATA[<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">sys</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(sys.version)
</span></span></code></pre></div><p>Output:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>3.9.7 (default, Aug 31 2021, 13:28:12)
</span></span><span style="display:flex;"><span>[GCC 11.1.0]
</span></span></code></pre></div>]]></description></item><item><title>You can use your database as a simple calculator</title><link>https://wangonya.com/blog/db-calc/</link><pubDate>Sat, 23 Oct 2021 17:49:32 +0300</pubDate><guid>https://wangonya.com/blog/db-calc/</guid><description><![CDATA[<p>Saw this in the <a href="https://dev.mysql.com/doc/refman/8.0/en/entering-queries.html">MySQL
docs</a>.
I&rsquo;m assuming this only works for relational databases.</p>
<p>I don&rsquo;t know if it&rsquo;s very useful but definitely interesting.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>MariaDB[] &gt; <span style="font-weight:bold">SELECT</span> SIN(PI()/4), (4+1)*5;
</span></span><span style="display:flex;"><span>+<span style="font-style:italic">------------------+---------+
</span></span></span><span style="display:flex;"><span>| SIN(PI()/4)      | (4+1)*5 |
</span></span><span style="display:flex;"><span>+<span style="font-style:italic">------------------+---------+
</span></span></span><span style="display:flex;"><span>| 0.70710678118655 |      25 |
</span></span><span style="display:flex;"><span>+<span style="font-style:italic">------------------+---------+
</span></span></span><span style="display:flex;"><span>1 <span style="font-weight:bold">row</span> <span style="font-weight:bold">in</span> <span style="font-weight:bold">set</span> (0.02 sec)
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span>postgres=# <span style="font-weight:bold">SELECT</span> SIN(PI()/4), (4+1)*5;
</span></span><span style="display:flex;"><span>        sin         | ?<span style="font-weight:bold">column</span>?
</span></span><span style="display:flex;"><span><span style="font-style:italic">--------------------+----------
</span></span></span><span style="display:flex;"><span> 0.7071067811865475 |       25
</span></span><span style="display:flex;"><span>(1 <span style="font-weight:bold">row</span>)
</span></span></code></pre></div>]]></description></item><item><title>Setting up PostgreSQL on Arch Linux</title><link>https://wangonya.com/blog/postgresql-setup-arch/</link><pubDate>Fri, 15 Oct 2021 16:09:08 +0300</pubDate><guid>https://wangonya.com/blog/postgresql-setup-arch/</guid><description><![CDATA[<p><a href="https://wiki.archlinux.org/title/PostgreSQL">Arch Linux PostgreSQL
docs</a></p>
<h2 id="install">Install</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo pacman -S postgresql
</span></span></code></pre></div><h2 id="setup-the-data-directory">Setup the data directory</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo -iu postgres
</span></span><span style="display:flex;"><span>[postgres]$ initdb -D /var/lib/postgres/data
</span></span></code></pre></div><h2 id="start-postgresqlservice">Start postgresql.service</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ systemctl start postgresql.service
</span></span><span style="display:flex;"><span>$ systemctl enable postgresql.service
</span></span></code></pre></div><h2 id="add-user">Add user</h2>
<pre><code>[postgres]$ createuser --interactive
</code></pre>
<h2 id="create-db">Create db</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ createdb myDatabaseName
</span></span></code></pre></div>]]></description></item><item><title>Setting up MariaDB on Arch Linux</title><link>https://wangonya.com/blog/mariadb-setup-arch/</link><pubDate>Fri, 15 Oct 2021 15:56:36 +0300</pubDate><guid>https://wangonya.com/blog/mariadb-setup-arch/</guid><description><![CDATA[<p><a href="https://wiki.archlinux.org/title/MariaDB">Arch Linux MariaDB docs</a></p>
<blockquote>
<p>MariaDB is a reliable, high performance and full-featured database
server which aims to be an &lsquo;always Free, backward compatible,
drop-in&rsquo; replacement of MySQL. Since 2013 MariaDB is Arch Linux&rsquo;s
default implementation of MySQL.</p>
</blockquote>
<h2 id="install">Install</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo pacman -S mariadb
</span></span></code></pre></div><h2 id="setup-the-data-directory">Setup the data directory</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
</span></span></code></pre></div><h2 id="start-mariadbservice">Start mariadb.service</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ systemctl start mariadb.service
</span></span><span style="display:flex;"><span>$ systemctl enable mariadb.service
</span></span></code></pre></div><h2 id="add-user">Add user</h2>
<blockquote>
<p>In the below example, the user monty with some_pass as password is
being created, then granted full permissions to the database mydb:</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ sudo mysql -u root -p
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>MariaDB&gt; CREATE USER <span style="font-style:italic">&#39;monty&#39;</span>@<span style="font-style:italic">&#39;localhost&#39;</span> IDENTIFIED BY <span style="font-style:italic">&#39;some_pass&#39;</span>;
</span></span><span style="display:flex;"><span>MariaDB&gt; GRANT ALL PRIVILEGES ON mydb.* TO <span style="font-style:italic">&#39;monty&#39;</span>@<span style="font-style:italic">&#39;localhost&#39;</span>;
</span></span><span style="display:flex;"><span>MariaDB&gt; FLUSH PRIVILEGES;
</span></span><span style="display:flex;"><span>MariaDB&gt; quit
</span></span></code></pre></div><h2 id="logging-into-mariadb">Logging into MariaDB</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>mysql -u //user_name// -p -h //ip_address// //db_name//
</span></span></code></pre></div><p>Eg:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>mysql -u username -ppassword -h localhost database_name
</span></span></code></pre></div>]]></description></item><item><title>Getting the running Go version</title><link>https://wangonya.com/blog/go-version/</link><pubDate>Sat, 24 Jul 2021 05:02:01 +0300</pubDate><guid>https://wangonya.com/blog/go-version/</guid><description><![CDATA[<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="font-weight:bold">package</span> main
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> (
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;log&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;runtime&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">func</span> main() {
</span></span><span style="display:flex;"><span>    log.Printf(<span style="font-style:italic">&#34;Running Go: %s&#34;</span>, runtime.Version())
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Output: <code>Running Go: go1.16.6</code></p>
]]></description></item><item><title>Writing DRYer tests using pytest parametrize</title><link>https://wangonya.com/blog/pytest-parametrize/</link><pubDate>Thu, 08 Apr 2021 17:08:41 +0300</pubDate><guid>https://wangonya.com/blog/pytest-parametrize/</guid><description><![CDATA[<p>Tests don&rsquo;t always need to be DRY, which isn&rsquo;t necessarily a bad
thing.</p>
<p><a href="https://stackoverflow.com/a/129722/9312256">This</a> SO answer sums it up
nicely:</p>
<blockquote>
<p>Readability is more important for tests. If a test fails, you want the
problem to be obvious. The developer shouldn&rsquo;t have to wade through a
lot of heavily factored test code to determine exactly what failed.
You don&rsquo;t want your test code to become so complex that you need to
write unit-test-tests.</p>
<p>However, eliminating duplication is usually a good thing, as long as
it doesn&rsquo;t obscure anything, and eliminating the duplication in your
tests may lead to a better API. Just make sure you don&rsquo;t go past the
point of diminishing returns.</p>
</blockquote>
<p>pytest gives some ways to reduce duplication with <code>parametrize</code>.</p>
<p>Say you had a couple of endpoints that return data to be used in a
report. The report data is supposed to be displayed in an excel sheet
with different sheets.</p>
<p>Sometimes, only data for one sheet is required. Other times, data for
all the sheets is fetched. So the endpoints end up being broken down
like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>/report/sheet-a
</span></span><span style="display:flex;"><span>/report/sheet-b
</span></span><span style="display:flex;"><span>/report/sheet-c
</span></span><span style="display:flex;"><span>/report/sheet-d
</span></span></code></pre></div><p>Let&rsquo;s take a simple test case: checking that the endpoints return
<code>200</code> when called.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_a_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-a&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_b_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-b&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_c_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-c&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_d_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-d&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span></code></pre></div><p>This might not look too bad, but if we wanted to test for another
operation on the endpoints - checking if the endpoints require
authentication for example - you get the feeling that this can be done a
little bit better.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># test GET requests</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_a_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-a&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_b_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-b&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_c_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-c&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_d_returns_200():
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">&#39;/report/sheet-d&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># test auth</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_a_requires_auth():
</span></span><span style="display:flex;"><span>    response = unauthorized_client.get(<span style="font-style:italic">&#39;/report/sheet-a&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 401
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_b_requires_auth():
</span></span><span style="display:flex;"><span>    response = unauthorized_client.get(<span style="font-style:italic">&#39;/report/sheet-b&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 401
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_c_requires_auth():
</span></span><span style="display:flex;"><span>    response = unauthorized_client.get(<span style="font-style:italic">&#39;/report/sheet-c&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 401
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheet_d_requires_auth():
</span></span><span style="display:flex;"><span>    response = unauthorized_client.get(<span style="font-style:italic">&#39;/report/sheet-d&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 401
</span></span></code></pre></div><p>Notice that the only thing changing in the tests is the endpoints.
Everything else remains the same.</p>
<p>Given that all the sheets belong to one report, we can refactor the
tests to reduce duplication without sacrificing readability.</p>
<p>Here&rsquo;s how the tests can be rewritten using <a href="https://docs.pytest.org/en/stable/parametrize.html#parametrize-basics">Pytest
parametrize</a>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>report_sheet_endpoints = (
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#39;/sheet-a&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#39;/sheet-b&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#39;/sheet-c&#39;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#39;/sheet-d&#39;</span>,
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@pytest.mark.parametrize(<span style="font-style:italic">&#39;endpoint&#39;</span>, report_sheet_endpoints)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheets_return_200(endpoint):
</span></span><span style="display:flex;"><span>    response = client.get(<span style="font-style:italic">f</span><span style="font-style:italic">&#39;/report</span><span style="font-weight:bold;font-style:italic">{</span>endpoint<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 200
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@pytest.mark.parametrize(<span style="font-style:italic">&#39;endpoint&#39;</span>, report_sheet_endpoints)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_report_sheets_require_auth(endpoint):
</span></span><span style="display:flex;"><span>    response = unauthorized_client.get(<span style="font-style:italic">f</span><span style="font-style:italic">&#39;/report</span><span style="font-weight:bold;font-style:italic">{</span>endpoint<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#39;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.status == 401
</span></span></code></pre></div><p>Now we have two tests instead of eight. But when you run the tests, 8
tests will run, not 2. Pytest takes each value in
<code>report_sheet_endpoints</code> and feeds it into the test. This
reduces duplication while maintaining readability.</p>
<p>Running the tests gives this output:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>test_reports.py::test_report_sheets_return_200[sheet-a] PASSED
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_return_200[sheet-b] PASSED
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_return_200[sheet-c] PASSED
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_return_200[sheet-d] PASSED
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_require_auth[sheet-a] PASSED
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_require_auth[sheet-b] PASSED
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_require_auth[sheet-c] PASSED
</span></span><span style="display:flex;"><span>test_reports.py::test_report_sheets_require_auth[sheet-d] PASSED
</span></span></code></pre></div>]]></description></item><item><title>What happens when you run PSQL slash commands?</title><link>https://wangonya.com/blog/psql-commands/</link><pubDate>Thu, 10 Dec 2020 05:51:19 +0300</pubDate><guid>https://wangonya.com/blog/psql-commands/</guid><description><![CDATA[<p>Running <code>\?</code> within a psql database gives a whole list of
commands that come in handy when performing various kinds of tasks.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ psql
</span></span><span style="display:flex;"><span>psql (13.0)
</span></span><span style="display:flex;"><span>Type <span style="font-style:italic">&#34;help&#34;</span> <span style="font-weight:bold">for</span> help.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>wangonya=<span style="font-style:italic"># \?</span>
</span></span><span style="display:flex;"><span>General
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold;font-style:italic">\c</span>opyright             show PostgreSQL usage and distribution terms
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold;font-style:italic">\c</span>rosstabview [COLUMNS] execute query and display results in crosstab
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold;font-style:italic">\e</span>rrverbose            show most recent error message at maximum verbosity
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  .....
</span></span></code></pre></div><p>But what are the queries executed when these commands run?</p>
<p>I was recently tasked to write a bash script that loops through every
schema on a database and does a <code>pg_dump</code> on it for backup
then uploads the backups to an external server.</p>
<p>Running <code>\dn</code> gives a list of schemas but it also gives the
owners, which I didn&rsquo;t need in my case.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>wangonya=<span style="font-style:italic"># \dn</span>
</span></span><span style="display:flex;"><span>  List of schemas
</span></span><span style="display:flex;"><span>  Name  |  Owner
</span></span><span style="display:flex;"><span>--------+----------
</span></span><span style="display:flex;"><span> public | wangonya
</span></span><span style="display:flex;"><span> x      | wangonya
</span></span><span style="display:flex;"><span> y      | wangonya
</span></span><span style="display:flex;"><span>(3 rows)
</span></span></code></pre></div><p>I only needed the schema names so I had to look for a way to edit the
query run by <code>\dn</code> to only return names.</p>
<p>From the psql <a href="https://www.postgresql.org/docs/13/app-psql.html">docs</a>:</p>
<blockquote>
<p><code>-E</code> &gt; <code>--echo-hidden</code></p>
<p>Echo the actual queries generated by <code>\d</code> and other
backslash commands. You can use this to study psql&rsquo;s internal
operations. This is equivalent to setting the variable ECHO_HIDDEN to
on.</p>
</blockquote>
<p>Running psql with the <code>-E</code> flag then running the
<code>/dn</code> command gives this result:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ psql -E
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>wangonya-# <span style="font-weight:bold;font-style:italic">\d</span>n
</span></span><span style="display:flex;"><span>********* QUERY **********
</span></span><span style="display:flex;"><span>SELECT n.nspname AS <span style="font-style:italic">&#34;Name&#34;</span>,
</span></span><span style="display:flex;"><span>  pg_catalog.pg_get_userbyid(n.nspowner) AS <span style="font-style:italic">&#34;Owner&#34;</span>
</span></span><span style="display:flex;"><span>FROM pg_catalog.pg_namespace n
</span></span><span style="display:flex;"><span>WHERE n.nspname !~ <span style="font-style:italic">&#39;^pg_&#39;</span> AND n.nspname &lt;&gt; <span style="font-style:italic">&#39;information_schema&#39;</span>
</span></span><span style="display:flex;"><span>ORDER BY 1;
</span></span><span style="display:flex;"><span>**************************
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  List of schemas
</span></span><span style="display:flex;"><span>  Name  |  Owner
</span></span><span style="display:flex;"><span>--------+----------
</span></span><span style="display:flex;"><span> public | wangonya
</span></span><span style="display:flex;"><span> x      | wangonya
</span></span><span style="display:flex;"><span> y      | wangonya
</span></span><span style="display:flex;"><span>(3 rows)
</span></span></code></pre></div><p>With the underlying query executed on running the slash command, I was
able to edit it to get the desired result.</p>
]]></description></item><item><title>Working with celery signals</title><link>https://wangonya.com/blog/celery-signals/</link><pubDate>Tue, 03 Nov 2020 06:17:15 +0300</pubDate><guid>https://wangonya.com/blog/celery-signals/</guid><description><![CDATA[<p>If you&rsquo;re new to celery, <a href="https://docs.celeryq.dev/en/stable/getting-started/first-steps-with-celery.html#first-steps">start
here</a>.</p>
<p>Sometimes when using celery, you may want to get notified when a task
running in the background executes successfully or when it fails. You
may also want to run a function each time before the celery task runs or
after it completes. These and many others along the same line are all
situations where
<a href="https://docs.celeryq.dev/en/stable/userguide/signals.html">signals</a>
would come in handy.</p>
<p>I&rsquo;ll create a simple file <code>tasks.py</code> and set up celery to
demonstrate how to use celery signals.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery</span> <span style="font-weight:bold">import</span> Celery
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app = Celery(<span style="font-style:italic">&#39;tasks&#39;</span>, broker=<span style="font-style:italic">&#39;redis://localhost:6379/0&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.task
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> add(x, y):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> x + y
</span></span></code></pre></div><p>Make sure your redis server is running and start your celery worker:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ celery -A tasks worker --loglevel=INFO
</span></span></code></pre></div><p>Then run your tasks.py file and execute the <code>add</code> task:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ python -i tasks.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; add.delay(4, 4)
</span></span><span style="display:flex;"><span>&lt;AsyncResult: ce1ee079-6434-4f54-ace2-360ff316546b&gt;
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span></code></pre></div><p>By default, what is returned is an
<a href="https://docs.celeryq.dev/en/stable/reference/celery.result.html#celery.result.AsyncResult">AsyncResult</a>
instance but that&rsquo;s not what we&rsquo;re interested in. On the terminal with
your Celery worker running, you should see something similar to this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>[2020-11-03 07:01:02,024: INFO/ForkPoolWorker-2] Task tasks.add[ce1ee079-6434-4f54-ace2-360ff316546b] succeeded in 0.0005510429999979749s: 8
</span></span></code></pre></div><p>The task executes successfully, and 8 is the result as expected.</p>
<h2 id="signals">Signals</h2>
<p>There are <a href="https://docs.celeryq.dev/en/stable/userguide/signals.html#signals">a
lot</a>
of signals that celery offers but I&rsquo;ll focus on 4 simple ones to
demonstrate how signals work in general.</p>
<ol>
<li>task_prerun</li>
<li>task_postrun</li>
<li>task_success</li>
<li>task_failure</li>
</ol>
<h3 id="task_prerun">task_prerun</h3>
<p>This signal is dispatched <strong>before</strong> a task is executed.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery</span> <span style="font-weight:bold">import</span> Celery
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery.signals</span> <span style="font-weight:bold">import</span> task_prerun
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app = Celery(<span style="font-style:italic">&#39;tasks&#39;</span>, broker=<span style="font-style:italic">&#39;redis://localhost:6379/0&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.task
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> add(x, y):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> x + y
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_prerun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_prerun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_prerun_notifier ==&gt; Running just before add() executes&#34;</span>)
</span></span></code></pre></div><p>Sender is the task object being executed (the <code>add</code> function
in this case).</p>
<p>Running <code>add.delay(4, 4)</code> like before now gives the following
output on the celery terminal:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>[2020-11-03 07:23:19,183: WARNING/ForkPoolWorker-2] From task_prerun_notifier ==&gt; Running just before add() executes
</span></span><span style="display:flex;"><span>[2020-11-03 07:23:19,184: INFO/ForkPoolWorker-2] Task tasks.add[1ef11c46-f461-4eb8-84ca-5c5cdab62a74] succeeded in 0.0016491969999998801s: 8
</span></span></code></pre></div><p>Just before the task runs, the signal dispatches and prints as expected.</p>
<h3 id="task_postrun">task_postrun</h3>
<p>Dispatched <strong>after</strong> a task has been executed.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery.signals</span> <span style="font-weight:bold">import</span> task_prerun, task_postrun
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app = Celery(<span style="font-style:italic">&#39;tasks&#39;</span>, broker=<span style="font-style:italic">&#39;redis://localhost:6379/0&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.task
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> add(x, y):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> x + y
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_prerun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_prerun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_prerun_notifier ==&gt; Running just before add() executes&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_postrun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_postrun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_postrun_notifier ==&gt; Ok, done!&#34;</span>)
</span></span></code></pre></div><p>Running this should give the following result:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>[2020-11-03 17:03:51,655: WARNING/ForkPoolWorker-2] From task_prerun_notifier ==&gt; Running just before add() executes
</span></span><span style="display:flex;"><span>[2020-11-03 17:03:51,656: INFO/ForkPoolWorker-2] Task tasks.add[7da6ee71-1941-4a87-b993-8136d94ac067] succeeded in 0.0017917519999999243s: 8
</span></span><span style="display:flex;"><span>[2020-11-03 17:03:51,657: WARNING/ForkPoolWorker-2] From task_postrun_notifier ==&gt; Ok, <span style="font-weight:bold">done</span>!
</span></span></code></pre></div><h3 id="task_success">task_success</h3>
<p>Dispatched when a task succeeds.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery</span> <span style="font-weight:bold">import</span> Celery
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery.signals</span> <span style="font-weight:bold">import</span> task_prerun, task_postrun, task_success
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app = Celery(<span style="font-style:italic">&#39;tasks&#39;</span>, broker=<span style="font-style:italic">&#39;redis://localhost:6379/0&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.task
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> add(x, y):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> x + y
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_prerun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_prerun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_prerun_notifier ==&gt; Running just before add() executes&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_postrun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_postrun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_postrun_notifier ==&gt; Ok, done!&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_success.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_success_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_success_notifier ==&gt; Task run successfully!&#34;</span>)
</span></span></code></pre></div><p>Result:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>[2020-11-03 17:40:47,276: INFO/MainProcess] Received task: tasks.add[6603eb49-75ab-4653-b32f-ebe760a52de0]
</span></span><span style="display:flex;"><span>[2020-11-03 17:40:47,279: WARNING/ForkPoolWorker-2] From task_prerun_notifier ==&gt; Running just before add() executes
</span></span><span style="display:flex;"><span>[2020-11-03 17:40:47,281: WARNING/ForkPoolWorker-2] From task_success_notifier ==&gt; Task run successfully!
</span></span><span style="display:flex;"><span>[2020-11-03 17:40:47,281: INFO/ForkPoolWorker-2] Task tasks.add[6603eb49-75ab-4653-b32f-ebe760a52de0] succeeded in 0.00201471799999986s: 8
</span></span><span style="display:flex;"><span>[2020-11-03 17:40:47,282: WARNING/ForkPoolWorker-2] From task_postrun_notifier ==&gt; Ok, <span style="font-weight:bold">done</span>!
</span></span></code></pre></div><h3 id="task_failure">task_failure</h3>
<p>Dispatched when a task fails.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery</span> <span style="font-weight:bold">import</span> Celery
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">celery.signals</span> <span style="font-weight:bold">import</span> task_prerun, task_postrun, task_failure
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app = Celery(<span style="font-style:italic">&#39;tasks&#39;</span>, broker=<span style="font-style:italic">&#39;redis://localhost:6379/0&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@app.task
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> add(x, y):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">raise</span> <span style="font-weight:bold">Exception</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_prerun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_prerun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_prerun_notifier ==&gt; Running just before add() executes&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_postrun.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_postrun_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_postrun_notifier ==&gt; Ok, done!&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@task_failure.connect(sender=add)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> task_failure_notifier(sender=<span style="font-weight:bold">None</span>, **kwargs):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;From task_failure_notifier ==&gt; Task failed successfully! 😅&#34;</span>)
</span></span></code></pre></div><p>Result:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>[2020-11-03 17:44:36,082: INFO/MainProcess] Received task: tasks.add[da4a03e8-5530-4c9e-afeb-75f8e0b1be5d]
</span></span><span style="display:flex;"><span>[2020-11-03 17:44:36,085: WARNING/ForkPoolWorker-2] From task_prerun_notifier ==&gt; Running just before add() executes
</span></span><span style="display:flex;"><span>[2020-11-03 17:44:36,096: WARNING/ForkPoolWorker-2] From task_failure_notifier ==&gt; Task failed successfully! 😅
</span></span><span style="display:flex;"><span>[2020-11-03 17:44:36,096: ERROR/ForkPoolWorker-2] Task tasks.add[da4a03e8-5530-4c9e-afeb-75f8e0b1be5d] raised unexpected: Exception()
</span></span><span style="display:flex;"><span>Traceback (most recent call last):
</span></span><span style="display:flex;"><span>  ...
</span></span><span style="display:flex;"><span>   in add
</span></span><span style="display:flex;"><span>    raise Exception
</span></span><span style="display:flex;"><span>Exception
</span></span><span style="display:flex;"><span>[2020-11-03 17:44:36,097: WARNING/ForkPoolWorker-2] From task_postrun_notifier ==&gt; Ok, <span style="font-weight:bold">done</span>!
</span></span></code></pre></div>]]></description></item><item><title>Shallow &amp; deep copying in Python</title><link>https://wangonya.com/blog/shallow-deep-copy-python/</link><pubDate>Sun, 21 Jun 2020 12:36:17 +0300</pubDate><guid>https://wangonya.com/blog/shallow-deep-copy-python/</guid><description><![CDATA[<p>What happens when a variable is assigned to another variable in python?
For example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; x = 5
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y = x
</span></span></code></pre></div><p>Both <code>x</code> and <code>y</code> will have the value
<code>5</code>. But, when <code>x</code> was assigned to <code>y</code>,
<code>y</code> was not created as a completely new/separate object.
Instead, an <strong>alias</strong> for <code>x</code> was created. That is,
<code>y</code> points to the memory location of <code>x</code>. It does
not have its own memory location - yet.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; id(x)
</span></span><span style="display:flex;"><span>140428600776960
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; id(y)
</span></span><span style="display:flex;"><span>140428600776960
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x is y
</span></span><span style="display:flex;"><span>True
</span></span></code></pre></div><p>You may never have any problems with this when working with <a href="https://stackoverflow.com/a/23715872">immutable
types</a> because the alias is broken
as soon as either of the two variables change.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; x += 2
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>7
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>5
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; id(x)
</span></span><span style="display:flex;"><span>140539682924864
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; id(y)
</span></span><span style="display:flex;"><span>140428600776960
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x is y
</span></span><span style="display:flex;"><span>False
</span></span></code></pre></div><p>But when working with mutable types, the alias is not broken when the
original is updated. This means changes in <code>x</code> would reflect
in <code>y</code>.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; x = [1,2,3]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y = x
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[1, 2, 3]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>[1, 2, 3]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x is y
</span></span><span style="display:flex;"><span>True
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x.append(4)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x.append(5)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[1, 2, 3, 4, 5]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>[1, 2, 3, 4, 5]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x is y
</span></span><span style="display:flex;"><span>True
</span></span></code></pre></div><p><code>y</code> was updated externally. This might be a cause of bugs if
for example a value is updated by an external library and other
variables are affected.</p>
<p>This can be prevented by creating shallow/deep copies of objects instead
of using assignment.</p>
<h2 id="shallow-copy">Shallow copy</h2>
<p>A shallow copy creates a new object, then populates it with references
of the <em>objects</em> in the original object. Continuing with the previous
example, a shallow copy can be created using either the
<code>list()</code> or <code>copy()</code> command.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; z = list(x)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[1, 2, 3, 4, 5]
</span></span></code></pre></div><p>Now if some more values are appended to <code>x</code>, <code>y</code>
will still be affected, but <code>z</code> will not.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; x.append(6)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x.append(7)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[1, 2, 3, 4, 5, 6, 7]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>[1, 2, 3, 4, 5, 6, 7]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[1, 2, 3, 4, 5]
</span></span></code></pre></div><p>However, a shallow copy doesn&rsquo;t fully solve the problem because even
though a new list was created, the objects in the list are still
references to the objects in <code>x</code>.</p>
<p>As it is currently, updating <code>x[0]</code> would not affect
<code>z[0]</code> because - immutable objects - the alias would be
broken. But, if we were dealing with a list of lists, an update in
<code>x[0]</code> would affect <code>z[0]</code>.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; x = [[1,2], [3,4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y = x
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z = list(x)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x.append([5,6])
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4], [5, 6]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4], [5, 6]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x[0][1] = <span style="font-style:italic">&#39;edited&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[[1, <span style="font-style:italic">&#39;edited&#39;</span>], [3, 4], [5, 6]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; y
</span></span><span style="display:flex;"><span>[[1, <span style="font-style:italic">&#39;edited&#39;</span>], [3, 4], [5, 6]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[[1, <span style="font-style:italic">&#39;edited&#39;</span>], [3, 4]]
</span></span></code></pre></div><h2 id="deep-copy">Deep copy</h2>
<p>A deep copy creates a new object, and completely new instances of the
objects in it. That is, a deep copied object is completely independent
of the original. Updating objects in the original would not affect the
deep copied object since there&rsquo;s no longer any connection.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; import copy
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x = [[1,2], [3,4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z = copy.deepcopy(x)
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x is z
</span></span><span style="display:flex;"><span>False
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x[0][1] = <span style="font-style:italic">&#39;edited&#39;</span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; x
</span></span><span style="display:flex;"><span>[[1, <span style="font-style:italic">&#39;edited&#39;</span>], [3, 4]]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; z
</span></span><span style="display:flex;"><span>[[1, 2], [3, 4]]
</span></span></code></pre></div>]]></description></item><item><title>Variables &amp; mutability in Rust</title><link>https://wangonya.com/blog/variables-mutability/</link><pubDate>Sun, 14 Jun 2020 22:33:13 +0300</pubDate><guid>https://wangonya.com/blog/variables-mutability/</guid><description><![CDATA[<p>By default, variables are immutable in Rust. Coming from a Python
background, I have to keep in mind that this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="font-weight:bold">fn</span> main() {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">let</span> var = 10;
</span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var = </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);  <span style="font-style:italic">// var = 10
</span></span></span><span style="display:flex;"><span>    var = 5;  <span style="font-style:italic">// try and reassign var
</span></span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var is now </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>&hellip; will not compile.</p>
<p>The rust compiler gives a clear output of what went wrong:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>error[E0384]: cannot assign twice to immutable variable <span style="font-style:italic">`</span>var<span style="font-style:italic">`</span>
</span></span><span style="display:flex;"><span>  |
</span></span><span style="display:flex;"><span>2 |     let var = 10;
</span></span><span style="display:flex;"><span>  |         ---
</span></span><span style="display:flex;"><span>  |         |
</span></span><span style="display:flex;"><span>  |         first assignment to <span style="font-style:italic">`</span>var<span style="font-style:italic">`</span>
</span></span><span style="display:flex;"><span>  |         help: make this binding mutable: <span style="font-style:italic">`</span>mut var<span style="font-style:italic">`</span>
</span></span><span style="display:flex;"><span>3 |     println!(<span style="font-style:italic">&#34;var = {}&#34;</span>, var);  // var = 10
</span></span><span style="display:flex;"><span>4 |     var = 5;  // try and reassign var
</span></span><span style="display:flex;"><span>  |     ^^^^^^^ cannot assign twice to immutable variable
</span></span></code></pre></div><p>Once a value is assigned to <code>var</code>, <code>var</code> is bound
to that value until it goes out of scope.</p>
<h2 id="opting-out-of-immutability">Opting out of immutability</h2>
<p>Variables can be made mutable using the <code>mut</code> keyword:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="font-weight:bold">fn</span> main() {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">let</span> <span style="font-weight:bold">mut</span> var = 10;
</span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var = </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);  <span style="font-style:italic">// var = 10
</span></span></span><span style="display:flex;"><span>    var = 5;  <span style="font-style:italic">// reassign var
</span></span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var is now </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);  <span style="font-style:italic">// var is now 5
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This makes it clear when reading the code that <code>var</code> expects
to be changed somewhere else.</p>
<h2 id="shadowing">Shadowing</h2>
<p>Instead of making a variable mutable and reassigning it directly, rust
provides another technique known as shadowing. Here&rsquo;s an example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="font-weight:bold">fn</span> main() {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">let</span> var = 10;  <span style="font-style:italic">// not mutable
</span></span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var = </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);  <span style="font-style:italic">// var = 10
</span></span></span><span style="display:flex;"><span>    <span style="font-weight:bold">let</span> var = 5;  <span style="font-style:italic">// shadow first var (10)
</span></span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var is now </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);  <span style="font-style:italic">// var is now 5
</span></span></span><span style="display:flex;"><span>    <span style="font-weight:bold">let</span> var = var + 2;  <span style="font-style:italic">// shadow second var (5) and add 2 to it
</span></span></span><span style="display:flex;"><span>    println!(<span style="font-style:italic">&#34;var + 2 = </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>, var);  <span style="font-style:italic">// var + 2 = 7
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>var</code> remains immutable all through so trying to attach any
value to it without using <code>let</code> to tell Rust you&rsquo;re
shadowing will not work.</p>
<p>Shadowing also allows changing the variable data type - something that
making a variable mutable doesn&rsquo;t allow. An example of when to use this
would be when writing a program that accepts a string and returns the
number of characters in that string.</p>
<p>This works:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="font-weight:bold">let</span> hello = <span style="font-style:italic">&#34;hello&#34;</span>;
</span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> hello = hello.len();  <span style="font-style:italic">// 5
</span></span></span></code></pre></div><p>This will not compile:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="font-weight:bold">let</span> <span style="font-weight:bold">mut</span> hello = <span style="font-style:italic">&#34;hello&#34;</span>;
</span></span><span style="display:flex;"><span>hello = hello.len();
</span></span></code></pre></div><p>Output:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>error[E0308]: mismatched types
</span></span><span style="display:flex;"><span>  |
</span></span><span style="display:flex;"><span>3 |     hello = hello.len();
</span></span><span style="display:flex;"><span>  |             ^^^^^^^^^^^ expected <span style="font-style:italic">`</span>&amp;str<span style="font-style:italic">`</span>, found <span style="font-style:italic">`</span>usize<span style="font-style:italic">`</span>
</span></span></code></pre></div><h2 id="variables-vs-constants">Variables vs constants</h2>
<ul>
<li>Constants are declared with <code>const</code> keyword, variables
with <code>let</code></li>
<li>Constants cannot be made mutable</li>
<li>Constants can only be assigned to constant expressions, not to
values that are computed during runtime - like results of function
calls</li>
</ul>
]]></description></item><item><title>When to use Python's enumerate() instead of range() in loops</title><link>https://wangonya.com/blog/python-enumerate/</link><pubDate>Sun, 26 Jan 2020 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/python-enumerate/</guid><description><![CDATA[<p>The <code>range()</code> function is often useful when iterating over a
set of integers:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">for</span> n <span style="font-weight:bold">in</span> range(50):
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">#</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> n <span style="font-weight:bold">in</span> range(10, 30):
</span></span><span style="display:flex;"><span>    ...
</span></span></code></pre></div><p>or a list of strings:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">for</span> fruit <span style="font-weight:bold">in</span> [<span style="font-style:italic">&#34;apple&#34;</span>, <span style="font-style:italic">&#34;mango&#34;</span>, <span style="font-style:italic">&#34;banana&#34;</span>]:
</span></span><span style="display:flex;"><span>    ...
</span></span></code></pre></div><p>Now, say you want to iterate over the list of fruits and also show the
index of the current item in the list. Using <code>range()</code>, this
might be done like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>fruits = [<span style="font-style:italic">&#34;apple&#34;</span>, <span style="font-style:italic">&#34;mango&#34;</span>, <span style="font-style:italic">&#34;banana&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> i <span style="font-weight:bold">in</span> range(len(fruits)):
</span></span><span style="display:flex;"><span>    fruit = fruits[i]
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">f</span><span style="font-style:italic">&#34;</span><span style="font-weight:bold;font-style:italic">{</span>i<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">: </span><span style="font-weight:bold;font-style:italic">{</span>fruit<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output:</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 0: apple</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 1: mango</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 2: banana</span>
</span></span></code></pre></div><p>It gets the job done, but not very pythonic. You have to get the length
of the list to keep track of the index, then index into the array to get
the current fruit - which makes the code more verbose and harder to
read.</p>
<h2 id="a-better-way-enumerate">A better way: <code>enumerate()</code></h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>fruits = [<span style="font-style:italic">&#34;apple&#34;</span>, <span style="font-style:italic">&#34;mango&#34;</span>, <span style="font-style:italic">&#34;banana&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> i, fruit <span style="font-weight:bold">in</span> enumerate(fruits):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">f</span><span style="font-style:italic">&#34;</span><span style="font-weight:bold;font-style:italic">{</span>i<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">: </span><span style="font-weight:bold;font-style:italic">{</span>fruit<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output:</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 0: apple</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 1: mango</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 2: banana</span>
</span></span></code></pre></div><p>Numbering can also be set to begin at any desired number.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>fruits = [<span style="font-style:italic">&#34;apple&#34;</span>, <span style="font-style:italic">&#34;mango&#34;</span>, <span style="font-style:italic">&#34;banana&#34;</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> i, fruit <span style="font-weight:bold">in</span> enumerate(fruits, 7):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">f</span><span style="font-style:italic">&#34;</span><span style="font-weight:bold;font-style:italic">{</span>i<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">: </span><span style="font-weight:bold;font-style:italic">{</span>fruit<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 7: apple</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 8: mango</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># 9: banana</span>
</span></span></code></pre></div>]]></description></item><item><title>difflib - finding close matches of strings from a list</title><link>https://wangonya.com/blog/difflib/</link><pubDate>Sun, 22 Sep 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/difflib/</guid><description><![CDATA[<p>Say we have a list of strings: <code>_list = [...,]</code> and user
input <code>_input = '...'</code>, how do we find the items in
<code>_list</code> that most closely resemble <code>_input</code>?</p>
<p>Python has a built-in package called <code>difflib</code> with the
function <code>get_close_matches()</code> that can help us.</p>
<p><code>get_close_matches(word, possibilities, n, cutoff)</code> accepts
four parameters:</p>
<ul>
<li><code>word</code> - the word to find close matches for in our list</li>
<li><code>possibilities</code> - the list in which to search for close
matches of <code>word</code></li>
<li><code>n</code> (optional) - the maximum number of close matches to
return. Must be <code>&gt; 0</code>. Default is <code>3</code>.</li>
<li><code>cutoff</code> (optional) - a float in the range [0, 1] that
a <code>possibility</code> must score in order to be considered
similar to <code>word</code>. <code>0</code> is very lenient,
<code>1</code> is very strict. Default is <code>0.6</code>.</li>
</ul>
<p>An example from the docs:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>Python 3.7.3
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; from difflib import get_close_matches
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; get_close_matches(<span style="font-style:italic">&#39;appel&#39;</span>, [<span style="font-style:italic">&#39;ape&#39;</span>, <span style="font-style:italic">&#39;apple&#39;</span>, <span style="font-style:italic">&#39;peach&#39;</span>, <span style="font-style:italic">&#39;puppy&#39;</span>])
</span></span><span style="display:flex;"><span>[<span style="font-style:italic">&#39;apple&#39;</span>, <span style="font-style:italic">&#39;ape&#39;</span>]
</span></span></code></pre></div><p>The above example can easily be modified to use a custom list
<code>_list</code> for <code>possibilities</code> and user input
<code>_input</code> for <code>word</code>.</p>
]]></description></item><item><title>HTML to JSX compiler</title><link>https://wangonya.com/blog/html-to-jsx-compiler/</link><pubDate>Mon, 09 Sep 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/html-to-jsx-compiler/</guid><description><![CDATA[<p>I just came across <a href="https://magic.reactjs.net/htmltojsx.htm">this</a>
online HTML to JSX Compiler. If you&rsquo;re new (or not) to react and
you&rsquo;re still having a little trouble with JSX, I think this tool is
great for learning.</p>
<p>Just paste in your HTML in the HTML editor on the left, and it&rsquo;ll be
converted into valid JSX on the right.</p>
]]></description></item><item><title>Python 'is' vs '=='</title><link>https://wangonya.com/blog/python-is-vs-/</link><pubDate>Fri, 06 Sep 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/python-is-vs-/</guid><description><![CDATA[<p>A lot of times when I&rsquo;m using <code>if</code> in Python, I find myself
wondering whether to use <code>is</code> or <code>==</code> for the
check.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># do I do</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> a <span style="font-weight:bold">is</span> b:
</span></span><span style="display:flex;"><span>    ...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># or</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> a == b:
</span></span><span style="display:flex;"><span>    ...
</span></span></code></pre></div><p>It can be a bit confusing if you&rsquo;re new to Python, and it&rsquo;s easy to
assume the two can be used interchangeably. So, what&rsquo;s the difference?</p>
<h2 id="is"><code>is</code></h2>
<p>The <code>is</code> operator checks if both elements point to the same
object. Let&rsquo;s fire up a python console to help illustrate this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ python3
</span></span><span style="display:flex;"><span>Python 3.7.4
</span></span><span style="display:flex;"><span>[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
</span></span><span style="display:flex;"><span>Type <span style="font-style:italic">&#34;help&#34;</span>, <span style="font-style:italic">&#34;copyright&#34;</span>, <span style="font-style:italic">&#34;credits&#34;</span> or <span style="font-style:italic">&#34;license&#34;</span> <span style="font-weight:bold">for</span> more information.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; a = []
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; b = []
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; c = a
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; a
</span></span><span style="display:flex;"><span>[]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; b
</span></span><span style="display:flex;"><span>[]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; c
</span></span><span style="display:flex;"><span>[]
</span></span><span style="display:flex;"><span>&gt;&gt;&gt;
</span></span></code></pre></div><p>So, we&rsquo;ve declared three variables and assigned them values.
<code>a</code> and <code>b</code> are both empty lists, and
<code>c = a</code>. We can see that all three variables contain an empty
list. Using <code>is</code> to compare them:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; a is b
</span></span><span style="display:flex;"><span>False
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; b is c
</span></span><span style="display:flex;"><span>False
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; a is c
</span></span><span style="display:flex;"><span>True
</span></span></code></pre></div><p>Despite the fact that <code>a</code> and <code>b</code> seem identical
(in that they&rsquo;re both empty lists), the variables <code>a</code> and
<code>b</code> do not point to the same object, therefore
<code>a is b</code> evaluates to <code>False</code>. The same goes for
<code>b is c</code>.</p>
<p>Conversely, because we assigned the variable <code>a</code> to
<code>c</code>, they both point to the same object, thus
<code>a is c</code> is <code>True</code>.</p>
<h2 id="heading"><code>==</code></h2>
<p><code>==</code> on the other hand checks if both elements contain equal
values. Whether or not they point to the same object doesn&rsquo;t matter
here.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; a == b
</span></span><span style="display:flex;"><span>True
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; b == c
</span></span><span style="display:flex;"><span>True
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; a == c
</span></span><span style="display:flex;"><span>True
</span></span></code></pre></div><p>All checks using <code>==</code> evaluate to <code>True</code>, because
the values of <code>a</code>, <code>b</code> and <code>c</code> are all
equal. If <code>d = [1, 2, 3]</code> is introduced, <code>a == d</code>,
<code>b == d</code> and <code>c == d</code> would all be
<code>False</code>, because the values are not equal.</p>
<p>So if you want to check that elements point to the same object, use
<code>is</code>. If you&rsquo;re only interested in the equality of the
values, use <code>==</code>.</p>
]]></description></item><item><title>Making your SMART goals smarter with stretch goals</title><link>https://wangonya.com/blog/stretch-smart-goals/</link><pubDate>Fri, 30 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/stretch-smart-goals/</guid><description><![CDATA[<p>I&rsquo;ve been reading the book &quot;Smarter Faster Better&quot; by Charles Duhigg
and in it, he gives a perspective on goal-setting that I found
interesting.</p>
<p>You may already know about <a href="https://www.mindtools.com/pages/article/smart-goals.htm">SMART
goals</a>, which
is an awesome format to set your goals in. It does have a subtle pitfall
though: cognitive closure.</p>
<h3 id="cognitive-closure">Cognitive closure</h3>
<blockquote>
<p>Cognitive closure (psychology), the human desire to eliminate
ambiguity and arrive at definite conclusions (sometimes
irrationally) -
<a href="https://en.wikipedia.org/wiki/Cognitive_closure">Wikipedia</a></p>
</blockquote>
<p>You know that nice feeling of crossing things off your to-do list?
Closure. Which is great, for the most part. It only gets bad when we end
up expending more effort to get immediate results, when we are so
focused on small daily &quot;wins&quot; that we lose focus on the larger
picture.</p>
<blockquote>
<p>&ldquo;You get into this mindset where crossing things off your to-do list
becomes more important than asking yourself if you&rsquo;re doing the right
things. - The book</p>
<p>&quot;To-do lists are great if you&rsquo;re using them correctly. But when
people say things like &lsquo;I sometimes write down easy items I can cross
off right away, because it makes me feel good&rsquo;, that&rsquo;s exactly the
<em>wrong</em> way to create a to-do list. That signals you&rsquo;re using it for
mood repair, rather than to become productive.&quot; - Timothy Pychyl,
quoted in the book</p>
</blockquote>
<p>I think it&rsquo;s easier to fall into this trap than most of us would like
to admit.</p>
<h3 id="combining-smart-goals-with-stretch-goals">Combining SMART goals with Stretch goals</h3>
<p>Stretch goals are goals that may be considered audacious, but
achievable. These are the kind of goals you may think about when asked
to &quot;dream big&quot;. The point is to have one major goal that is not
immediately achievable, then use the SMART strategy to form sub-goals
that move you closer to achieving the main goal. Here&rsquo;s an example from
the book:</p>
<ul>
<li>Stretch goal: run a marathon</li>
<li>Specific sub-goal: run 7 miles without stopping</li>
<li>Measurable: run twice around the park, no walking</li>
<li>Achievable?: yes, if I run 3 times a week</li>
<li>Realistic?: yes, if I wake up early on Mondays, Wednesdays, and
Fridays</li>
<li>Timeline: run 3 miles this week, 4 miles next week, 5 miles&hellip;</li>
</ul>
<p>Setting goals in this format ensures that we do get those small daily
wins, and always stay focused on the big picture.</p>
]]></description></item><item><title>Automatically counting and numbering HTML elements with CSS counters</title><link>https://wangonya.com/blog/css-counters/</link><pubDate>Sat, 24 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/css-counters/</guid><description><![CDATA[<p>Say you had an unknown number of <code>&lt;div&gt;</code> elements and (for
some reason) you wanted to count them and number each of them
automatically - how would you do it? If you&rsquo;re like me, your first
thought would be to use some kind of Javascript to play around with the
DOM. What if I told you (insert Morpheus voice here) you can do it with
CSS?</p>
<h2 id="how-to-use-css-counters">How to use CSS counters</h2>
<p>Getting counters working requires three steps:</p>
<ul>
<li>Initialize the counter with <code>counter-reset</code></li>
<li>Increment the counter with <code>counter-increment</code></li>
<li>Show the current counter value with <code>counter()</code></li>
</ul>
<p>It&rsquo;s pretty simple, really. The Pen below demonstrates how to count and
number three <code>&lt;div&gt;</code> elements.</p>
<iframe height="265" style="width: 100%;" scrolling="no" title="Css counter demo" src="//codepen.io/wang0nya/embed/voRyaJ/?height=265&amp;theme-id=dark&amp;default-tab=css,result" frameborder="no" allowtransparency="true" allowfullscreen="true"></iframe>
<h2 id="where-would-this-be-useful">Where would this be useful?</h2>
<p>I discovered CSS counters while looking for a way to number images on my
blog posts. That&rsquo;s one place it would really come in handy. Here&rsquo;s a
quick example:</p>
<iframe height="265" style="width: 100%;" scrolling="no" title="Css counter figcaptions demo" src="//codepen.io/wang0nya/embed/LwdxZz/?height=265&amp;theme-id=dark&amp;default-tab=html,result" frameborder="no" allowtransparency="true" allowfullscreen="true"></iframe>
]]></description></item><item><title>Publishing your Python packages on TestPyPi before publishing on PyPi</title><link>https://wangonya.com/blog/publishing-package-on-test-pypi/</link><pubDate>Fri, 23 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/publishing-package-on-test-pypi/</guid><description><![CDATA[<p>If you&rsquo;re just creating a package for learning purposes, there&rsquo;s no
need (IMO) to pollute the official PyPi index with it. Also, you may
want to release a package to a select number of users for testing before
you actually release it officially. For these purposes, you&rsquo;re better
off using <a href="https://test.pypi.org/">TestPyPi</a>:</p>
<blockquote>
<p>a separate instance of the Python Package Index that allows you to try
distribution tools and processes without affecting the real index.</p>
</blockquote>
<h2 id="uploading-to-testpypi">Uploading to TestPyPi</h2>
<p>For the final part of this series, I&rsquo;ll upload the app we created on
TestPyPi. Here are the steps to follow:</p>
<h3 id="1-create-an-account-on-testpypi">1. Create an account on TestPyPi</h3>
<p>You&rsquo;ll need an account to continue so head over to
<a href="https://test.pypi.org/">https://test.pypi.org/</a> and create one.</p>
<h3 id="2-update-setuppy">2. Update <code>setup.py</code></h3>
<p>We kept the <code>setup.py</code> file very simple during development.
Now we&rsquo;ll need to add some details to make it ready for publishing.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">setuptools</span> <span style="font-weight:bold">import</span> setup, find_packages
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">with</span> open(<span style="font-style:italic">&#34;README.md&#34;</span>, <span style="font-style:italic">&#34;r&#34;</span>) <span style="font-weight:bold">as</span> fh:
</span></span><span style="display:flex;"><span>    long_description = fh.read()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setup(
</span></span><span style="display:flex;"><span>        name=<span style="font-style:italic">&#34;contacts&#34;</span>,
</span></span><span style="display:flex;"><span>        version=<span style="font-style:italic">&#34;0.1.0&#34;</span>,
</span></span><span style="display:flex;"><span>        packages=find_packages(),
</span></span><span style="display:flex;"><span>        description=<span style="font-style:italic">&#34;Save contacts from your terminal&#34;</span>,
</span></span><span style="display:flex;"><span>        long_description=long_description,
</span></span><span style="display:flex;"><span>        long_description_content_type=<span style="font-style:italic">&#34;text/markdown&#34;</span>,
</span></span><span style="display:flex;"><span>        url=<span style="font-style:italic">&#34;https://github.com/wangonya/contacts-cli&#34;</span>,
</span></span><span style="display:flex;"><span>        author=<span style="font-style:italic">&#34;Kelvin Wangonya&#34;</span>,
</span></span><span style="display:flex;"><span>        author_email=<span style="font-style:italic">&#34;kwangonya@gmail.com&#34;</span>,
</span></span><span style="display:flex;"><span>        license=<span style="font-style:italic">&#34;MIT&#34;</span>,
</span></span><span style="display:flex;"><span>        classifiers=[
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;License :: OSI Approved :: MIT License&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;Programming Language :: Python :: 3&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;Programming Language :: Python :: 3.7&#34;</span>,
</span></span><span style="display:flex;"><span>        ],
</span></span><span style="display:flex;"><span>        install_requires=[
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;Click&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;requests&#34;</span>,
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>        entry_points=<span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        [console_scripts]
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        contacts=app:cli
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        &#34;&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>        )
</span></span></code></pre></div><p>Most of the options are self-explanatory, but you can check what each of
them means in the <a href="https://setuptools.readthedocs.io/en/latest/setuptools.html#new-and-changed-setup-keywords">setup
docs</a>.</p>
<h3 id="3-build-your-package">3. Build your package</h3>
<p>In the root directory, run:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ python setup.py sdist bdist_wheel
</span></span></code></pre></div><p>This will generate a <code>dist</code> folder with the distribution
packages:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>dist/
</span></span><span style="display:flex;"><span>├── contacts-0.1.0-py3-none-any.whl
</span></span><span style="display:flex;"><span>└── contacts-0.1.0.tar.gz
</span></span></code></pre></div><h3 id="4-upload-your-package-with-twine">4. Upload your package with twine</h3>
<p>Install twine:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ pip install twine
</span></span></code></pre></div><p>Upload your package:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ twine upload --repository-url https://test.pypi.org/legacy/ dist/*
</span></span><span style="display:flex;"><span>Enter your username: wangonya
</span></span><span style="display:flex;"><span>Enter your password:
</span></span><span style="display:flex;"><span>Uploading distributions to https://test.pypi.org/legacy/
</span></span><span style="display:flex;"><span>Uploading contacts-0.1.0-py3-none-any.whl
</span></span><span style="display:flex;"><span>100%|███████████████████████████████████████████████████████████|
</span></span><span style="display:flex;"><span>Uploading contacts-0.1.0.tar.gz
</span></span><span style="display:flex;"><span>100%|███████████████████████████████████████████████████████████|
</span></span></code></pre></div><p>The package should now be uploaded on your account.</p>
<p>To install the package locally from TestPyPi, run:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple your-package
</span></span></code></pre></div><p><code>--index-url</code> tells pip to get the package from TestPyPi. If
the package needs other dependencies to run,
<code>--extra-index-url</code> has to be included so the dependencies
can be fetched from the PyPi.</p>
]]></description></item><item><title>Testing Click applications with pytest</title><link>https://wangonya.com/blog/testing-click-with-pytest/</link><pubDate>Tue, 20 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/testing-click-with-pytest/</guid><description><![CDATA[<p>It&rsquo;s good practice to, as much as possible, write tests for your code.
If you&rsquo;re working with Python, <a href="https://pytest.org/en/latest/">pytest</a>
makes the process of writing and running tests much smoother. I wrote a
few posts some time back on getting started with testing with pytest, so
if you&rsquo;re completely new to it, you might want to take a look at them:</p>
<ul>
<li><a href="https://wangonya.com/blog/getting-started-with-pytest/">Getting started with
pytest</a></li>
<li><a href="https://wangonya.com/blog/pytest-asserting-exceptions/">Asserting Exceptions with
Pytest</a></li>
<li><a href="https://wangonya.com/blog/pytest-capture-print/">Capturing print statements while
debugging</a></li>
<li><a href="https://wangonya.com/blog/pytest-skip/">Skipping tests</a></li>
</ul>
<p>For testing CLI apps, Click provides a convenient module:
<code>click.testing</code> which has some useful functions (notably
<code>CliRunner()</code>) to help us invoke commands and check their
behavior.</p>
<p>We&rsquo;ll go ahead and test each part of <a href="https://wangonya.com/blog/cli-crud-with-firebase/">our
app</a> - creating,
reading, updating and deleting.</p>
<h3 id="installing-pytest-and-writing-the-first-test">Installing pytest and writing the first test</h3>
<p>pytest can be installed via pip:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ pip install pytest
</span></span></code></pre></div><p>After installing pytest, create a tests folder in the root directory and
add the first test file:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ mkdir tests &amp;&amp; cd tests
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(env) $ touch test_app.py
</span></span></code></pre></div><p>In the test_app file, add the following code for a start:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_add():
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span></code></pre></div><p>To run the test, run <code>pytest</code> on the terminal:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ pytest
</span></span><span style="display:flex;"><span>================== test session starts ====================
</span></span><span style="display:flex;"><span>platform linux -- Python 3.7.3, pytest-5.1.0, py-1.8.0, pluggy-0.12.0
</span></span><span style="display:flex;"><span>rootdir: /home/wangonya/code/contacts-cli
</span></span><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>tests/test_app.py .                              [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>================== 1 passed in 0.04s =======================
</span></span></code></pre></div><h3 id="testing-the-add-command">Testing the <code>add</code> command</h3>
<p>Let&rsquo;s edit the test_app file to add a test to see if the
<code>add</code> command adds a new contact:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">click.testing</span> <span style="font-weight:bold">import</span> CliRunner
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">app</span> <span style="font-weight:bold">import</span> add
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>runner = CliRunner()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_add():
</span></span><span style="display:flex;"><span>    response = runner.invoke(add, [<span style="font-style:italic">&#34;test-user&#34;</span>, <span style="font-style:italic">&#34;-m&#34;</span>, <span style="font-style:italic">&#34;0&#34;</span>])
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.exit_code == 0
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Contact test-user added!&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;{&#39;mobile&#39;: &#39;0&#39;}&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span></code></pre></div><p>First, we invoke the command as we would on the terminal, passing in the
required arguments and options:
<code>response = runner.invoke(add, [&quot;test-user&quot;, &quot;-m&quot;, &quot;0&quot;])</code>.</p>
<p>We then check that the command executes successfully:
<code>assert response.exit_code == 0</code>.</p>
<p>If the command executes successfully, we expect a success message should
be returned in the response with the values we added:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Contact test-user added!&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span><span style="display:flex;"><span><span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;{&#39;mobile&#39;: &#39;0&#39;}&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span></code></pre></div><p>The rest of the tests will pretty much follow the same format.</p>
<h3 id="testing-the-list-command">Testing the <code>list</code> command</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_list():
</span></span><span style="display:flex;"><span>    response = runner.invoke(list)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.exit_code == 0
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Here&#39;s a list of all your contacts:&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;&#39;test-user&#39;: {&#39;mobile&#39;: &#39;0&#39;}&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span></code></pre></div><p>The list command doesn&rsquo;t take any arguments or options so we just call
it directly: <code>response = runner.invoke(list)</code>.</p>
<h3 id="testing-the-view-command">Testing the <code>view</code> command</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_view():
</span></span><span style="display:flex;"><span>    response = runner.invoke(view, <span style="font-style:italic">&#34;test-user&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.exit_code == 0
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;{&#39;mobile&#39;: &#39;0&#39;}&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span></code></pre></div><h3 id="testing-the-update-command">Testing the <code>update</code> command</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_update():
</span></span><span style="display:flex;"><span>    response = runner.invoke(update, [<span style="font-style:italic">&#34;test-user&#34;</span>, <span style="font-style:italic">&#34;-m&#34;</span>, <span style="font-style:italic">&#34;12345&#34;</span>])
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.exit_code == 0
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Contact updated!&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;{&#39;mobile&#39;: &#39;12345&#39;}&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span></code></pre></div><h3 id="testing-the-delete-command">Testing the <code>delete</code> command</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_delete():
</span></span><span style="display:flex;"><span>    response = runner.invoke(delete, <span style="font-style:italic">&#34;test-user&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.exit_code == 0
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Contact deleted!&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-style:italic"># call view on test-user to confirm it doesn&#39;t exist</span>
</span></span><span style="display:flex;"><span>    response = runner.invoke(view, <span style="font-style:italic">&#34;test-user&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> response.exit_code == 0
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;The contact you searched for doesn&#39;t exist&#34;</span> <span style="font-weight:bold">in</span> response.output
</span></span></code></pre></div><h3 id="improvements">Improvements</h3>
<p>As your application grows, you may want to consider using
<a href="https://docs.pytest.org/en/latest/fixture.html">fixtures</a> and set up
things like <code>runner</code> in a <code>conftest.py</code> file. We
got away with it here because our tests were simple and all in a single
file. Once multiple test files are introduced, following the approach we
used here would lead to a lot of unnecessarily duplicated code.</p>
<p>Also, we made direct calls to our API in the tests. This operation
should ideally be mocked.</p>
]]></description></item><item><title>Performing CRUD operations with a CLI app using Firebase</title><link>https://wangonya.com/blog/cli-crud-with-firebase/</link><pubDate>Thu, 15 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/cli-crud-with-firebase/</guid><description><![CDATA[<p>For the next phase in this series, we&rsquo;ll learn how to make a CLI app to
perform CRUD operations, i.e., Creating, Retrieving, Updating and
Deleting data. We&rsquo;ll use Firebase to store our data.</p>
<h3 id="what-well-create">What we&rsquo;ll create</h3>
<p>A <code>contacts</code> app with the following functionality:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="font-style:italic"># add a new contact with name=Peter and mobile=01034512</span>
</span></span><span style="display:flex;"><span>$ contacts add Peter --mobile 01034512
</span></span><span style="display:flex;"><span>Contact Peter added!
</span></span><span style="display:flex;"><span>{ <span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;01034512&#39;</span> }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="font-style:italic"># view all contacts</span>
</span></span><span style="display:flex;"><span>$ contacts list
</span></span><span style="display:flex;"><span>Here<span style="">&#39;</span>s a list of all your contacts:
</span></span><span style="display:flex;"><span>{ ...  <span style="font-style:italic"># list of all contacts }</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="font-style:italic"># view single contact</span>
</span></span><span style="display:flex;"><span>$ contacts view Peter
</span></span><span style="display:flex;"><span>{ <span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;01034512&#39;</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ contacts view Meg
</span></span><span style="display:flex;"><span>The contact you searched <span style="font-weight:bold">for</span> doesn<span style="">&#39;</span>t exist
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="font-style:italic"># update mobile number for Peter</span>
</span></span><span style="display:flex;"><span>$ contacts update Peter --mobile 00000
</span></span><span style="display:flex;"><span>Contact updated!
</span></span><span style="display:flex;"><span>{ <span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;00000&#39;</span> }
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="font-style:italic"># delete the contact Peter</span>
</span></span><span style="display:flex;"><span>$ contacts delete Peter
</span></span><span style="display:flex;"><span>Contact deleted!
</span></span></code></pre></div><p>This post is a bit long. If you just want to take a look at the code or
see how the app works, check out <a href="https://github.com/wangonya/contacts-cli">the
repo</a>.</p>
<h3 id="setting-up-firebase">Setting up Firebase</h3>
<p>As mentioned earlier, Firebase will be used to store our data. To set up
the database, sign in on Firebase using your google account.</p>
<p>After signing in successfully, click on the <strong>Go to console</strong> button on
the top right. There, you can create a new project. Follow the required
steps to create a new project.</p>
<p>Once the project is created, you&rsquo;ll see a <strong>Develop</strong> sidebar on the
left. Click on <strong>Database</strong> to set up the database. <strong>Cloud Firestore</strong>
will be displayed as the first option but that&rsquo;s not what we&rsquo;ll be
using. Scroll down and you&rsquo;ll see a <strong>Realtime Database</strong> option. Click
on <strong>Create database</strong>. Next, you&rsquo;ll be presented with the security
options.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NW18o5Cl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oxot8m2sd0u5k68byq5k.png" alt="Firebase security rules
options">
</p>
<p>Since we&rsquo;ll not be handling authentication, choose <strong>Start in test
mode</strong> for the security rules. Your database is now created 🎉</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aoo7zOSH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/90prefpskmno1yxqb76k.png" alt="Empty firebase
db">
</p>
<p>Now for the final step in setting up the database, click on the little
plus sign <strong>+</strong> to add a new child node called <strong>contacts</strong>. This will
hold our contacts (obviously 😅). Also, add a test contact just to see
how the database will be structured.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4NmGuDlH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q7o4dahnowf1h9orx6vn.png" alt="Adding a new node to hold our
data">
</p>
<p>The database should now look like this:</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kRzFTe1G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/gcupu18rh3ieh1xhdks7.png" alt="Final
result">
</p>
<h3 id="app-setup">App setup</h3>
<p>We&rsquo;ve already gone through the basics of setting up in previous posts
so I won&rsquo;t go into much detail on that. Here are the steps:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ mkdir contacts-cli
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ cd contacts-cli
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ virtualenv env
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>$ . env/bin/activate
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(env) $ mkdir app
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(env) $ touch app/__init__.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(env) $ touch setup.py
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(env) $ touch .env
</span></span></code></pre></div><h3 id="env"><code>.env</code></h3>
<p>This is where the api endpoint url will be stored. Firebase <a href="https://firebase.google.com/docs/reference/rest/database">provides a
REST API</a> for
the database so that&rsquo;s what we&rsquo;ll use. If you already followed the
steps and created the database, just grab the link provided at the top
of the database and set it in your <code>.env</code> file.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>export URL=https://[YOUR_PROJECT_ID].firebaseio.com
</span></span></code></pre></div><p>Make sure to run <code>. .env</code> to load your environment variables,
otherwise <code>URL</code> will be <code>None</code>.</p>
<h3 id="setuppy"><code>setup.py</code></h3>
<p>To learn more about the <code>setup</code> file, you can go back to
<a href="https://wangonya.com/blog/using-setuptools/">this</a> post.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">setuptools</span> <span style="font-weight:bold">import</span> setup, find_packages
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setup(
</span></span><span style="display:flex;"><span>        name=<span style="font-style:italic">&#34;contacts&#34;</span>,
</span></span><span style="display:flex;"><span>        py_modules=find_packages(),
</span></span><span style="display:flex;"><span>        install_requires=[
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;Click&#34;</span>,
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;requests&#34;</span>,
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>        entry_points=<span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        [console_scripts]
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        contacts=app:cli
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        &#34;&#34;&#34;</span>,
</span></span><span style="display:flex;"><span>        )
</span></span></code></pre></div><p>Then run <code>pip install --editable .</code> in your terminal to
install the app.</p>
<ol>
<li><code>app/__init__.py</code></li>
</ol>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.group(invoke_without_command=<span style="font-weight:bold">True</span>)
</span></span><span style="display:flex;"><span>@click.pass_context
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> cli(ctx):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> ctx.invoked_subcommand <span style="font-weight:bold">is</span> <span style="font-weight:bold">None</span>:
</span></span><span style="display:flex;"><span>        click.echo(<span style="font-style:italic">&#34;Welcome to the contacts app 🥳&#34;</span>)
</span></span><span style="display:flex;"><span>        click.echo(<span style="font-style:italic">&#34;Run contacts --help for options.&#34;</span>)
</span></span></code></pre></div><p>We need to use <code>@click.group</code> to allow us to include
sub-commands.</p>
<p>If the main command is invoked without any sub-command, a welcome
message is shown. How does the main command know if a sub-command
has been passed in or not? By looking at the context.
<code>if ctx.invoked_subcommand is None</code>, then no sub-command
has been passed - show the welcome message.</p>
<p>Everything is set up now, so we can start working on the
functionality.</p>
<h2 id="creating-contacts">Creating contacts</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">os</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">requests</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@cli.command()
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;name&#39;</span>)
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;--mobile&#39;</span>, <span style="font-style:italic">&#39;-m&#39;</span>, required=<span style="font-weight:bold">True</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> add(name, mobile):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    Add a new contact
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    response = requests.put(<span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">/contacts/</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">.json&#39;</span>
</span></span><span style="display:flex;"><span>                            .format(os.getenv(<span style="font-style:italic">&#39;URL&#39;</span>), name),
</span></span><span style="display:flex;"><span>                            json={<span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#39;</span>.format(mobile)})
</span></span><span style="display:flex;"><span>    click.echo(<span style="font-style:italic">&#39;Contact </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic"> added!&#39;</span>.format(name))
</span></span><span style="display:flex;"><span>    click.echo(response.json())
</span></span></code></pre></div><p>You&rsquo;ll notice that I used <code>PUT</code> for the request instead of
<code>POST</code>. I did this to avoid generating unique IDs for my data
on Firebase. Feel free to use <code>POST</code> instead and see how you
can work with the generated UIDs.</p>
<p>The <code>add</code> command takes two parameters - a <code>name</code>
argument, and a <code>mobile</code> option. Both are required. Running
<code>contacts add --help</code> shows us what options we have.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ contacts add --help
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Usage: contacts add [OPTIONS] NAME
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  Add a new contact
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Options:
</span></span><span style="display:flex;"><span>  -m, --mobile TEXT  [required]
</span></span><span style="display:flex;"><span>  --help             Show this message and exit.
</span></span></code></pre></div><p>Let&rsquo;s add a new contact:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ contacts add Chris -m 34243234
</span></span><span style="display:flex;"><span>Contact Chris added!
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;34243234&#39;</span>}
</span></span></code></pre></div><p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ohYLYRV4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9tjntrzz3lnck3hcrg1l.png" alt="Contacts
database">
</p>
<h3 id="getting-all-contacts">Getting all contacts</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@cli.command()
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> list():
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    View all contacts
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    response = requests.get(<span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">/contacts.json&#39;</span>
</span></span><span style="display:flex;"><span>                            .format(os.getenv(<span style="font-style:italic">&#39;URL&#39;</span>)))
</span></span><span style="display:flex;"><span>    click.echo(<span style="font-style:italic">&#39;Here&#39;</span>s a list of all your contacts:<span style="font-style:italic">&#39;)</span>
</span></span><span style="display:flex;"><span>    click.echo(response.json())
</span></span></code></pre></div><p>The <code>list</code> command simply does a <code>GET</code> request on
the contacts node and returns the result.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ contacts list
</span></span><span style="display:flex;"><span>Here<span style="font-style:italic">&#39;s a list of all your contacts:
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">{&#39;</span>Chris<span style="font-style:italic">&#39;: {&#39;</span>mobile<span style="font-style:italic">&#39;: &#39;</span>34243234<span style="font-style:italic">&#39;}, &#39;</span>Peter<span style="font-style:italic">&#39;: {&#39;</span>mobile<span style="font-style:italic">&#39;: &#39;</span>8487344<span style="">&#39;</span>}}
</span></span></code></pre></div><h3 id="getting-one-contact">Getting one contact</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@cli.command()
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;name&#39;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> view(name):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    View single contact
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    response = requests.get(<span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">/contacts/</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">.json&#39;</span>
</span></span><span style="display:flex;"><span>                            .format(os.getenv(<span style="font-style:italic">&#39;URL&#39;</span>), name))
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> response.json():
</span></span><span style="display:flex;"><span>        click.echo(<span style="font-style:italic">&#34;The contact you searched for doesn&#39;t exist&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.json())
</span></span></code></pre></div><p>The <code>view</code> command is similar to <code>list</code>, except it
takes a <code>name</code> argument and adds it to the url to return the
contact for that name only. If the name doesn&rsquo;t exist in the database,
<code>null</code> is returned. We take advantage of that in the
<code>if</code> block to return the appropriate response.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ contacts view Peter
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;8487344&#39;</span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(env) $ contacts view Meg
</span></span><span style="display:flex;"><span>The contact you searched <span style="font-weight:bold">for</span> doesn<span style="">&#39;</span>t exist
</span></span></code></pre></div><h3 id="updating-a-contact">Updating a contact</h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@cli.command()
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;name&#39;</span>)
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;--mobile&#39;</span>, <span style="font-style:italic">&#39;-m&#39;</span>, required=<span style="font-weight:bold">True</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> update(name, mobile):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    Update contact
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    response = requests.patch(<span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">/contacts/</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">.json&#39;</span>
</span></span><span style="display:flex;"><span>                              .format(os.getenv(<span style="font-style:italic">&#39;URL&#39;</span>), name),
</span></span><span style="display:flex;"><span>                              json={<span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#39;</span>.format(mobile)})
</span></span><span style="display:flex;"><span>    click.echo(<span style="font-style:italic">&#39;Contact updated!&#39;</span>)
</span></span><span style="display:flex;"><span>    click.echo(response.json())
</span></span></code></pre></div><p>This works exactly the same as the create command, except we&rsquo;re using
<code>PATCH</code> instead of <code>PUT</code> (which apparently,
doesn&rsquo;t make any difference here. Making a <code>PATCH</code> on a
non-existent node creates it, just like <code>PUT</code> would do. Try
it out.)</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ contacts update Peter -m 552
</span></span><span style="display:flex;"><span>Contact updated!
</span></span><span style="display:flex;"><span>{<span style="font-style:italic">&#39;mobile&#39;</span>: <span style="font-style:italic">&#39;552&#39;</span>}
</span></span></code></pre></div><h3 id="and-finally-deleting-a-contact">And finally, deleting a contact</h3>
<p>Similar to the <code>view</code> command. The only change we&rsquo;ll make is
using <code>DELETE</code> instead of <code>GET</code>.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@cli.command()
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;name&#39;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> delete(name):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    Delete contact
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    &#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    requests.delete(<span style="font-style:italic">&#39;</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">/contacts/</span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">.json&#39;</span>
</span></span><span style="display:flex;"><span>                    .format(os.getenv(<span style="font-style:italic">&#39;URL&#39;</span>), name))
</span></span><span style="display:flex;"><span>    click.echo(<span style="font-style:italic">&#39;Contact deleted!&#39;</span>)
</span></span></code></pre></div><p><code>null</code> is returned on successful deletion so we don&rsquo;t
need to return <code>response</code>. The <code>request</code> is
called directly, and a success message is shown afterwards. This can be
done better but it&rsquo;ll do for now.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(env) $ contacts delete Peter
</span></span><span style="display:flex;"><span>Contact deleted!
</span></span></code></pre></div><p>I meant to cover exporting (writing) the data to a local JSON file or
sqlite database, but this post is already too long. These are
interesting things to try if you want to learn more.</p>
<p>In the next post, we&rsquo;ll add tests to the app using pytest.</p>
]]></description></item><item><title>Prompting users for input</title><link>https://wangonya.com/blog/prompting-users-for-input/</link><pubDate>Sat, 10 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/prompting-users-for-input/</guid><description><![CDATA[<p>Getting user input is an important part of any kind of application.
Since we&rsquo;ve already learned about
<a href="https://wangonya.com/blog/click-commands-options/">options</a>, adding a
user prompt to our hello world app should be a breeze. All we need to do
is add <code>prompt=True</code> to the option decorator, so that it
prompts the user for input if no option is passed in.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># helloworld.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;-c&#39;</span>, <span style="font-style:italic">&#39;--case&#39;</span>,
</span></span><span style="display:flex;"><span>              type=click.Choice([<span style="font-style:italic">&#39;upper&#39;</span>, <span style="font-style:italic">&#39;lower&#39;</span>]),
</span></span><span style="display:flex;"><span>              prompt=<span style="font-weight:bold">True</span>)
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;person&#39;</span>, default=<span style="font-style:italic">&#39;you&#39;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello(<span style="font-weight:bold">case</span>, person):
</span></span><span style="display:flex;"><span>    response = <span style="font-style:italic">&#34;Hello World! Also, hey </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic"> ☺️&#34;</span>.format(person)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;upper&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.upper())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">elif</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;lower&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.lower())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        click.echo(response)
</span></span></code></pre></div><p>Save and run the app:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello
</span></span><span style="display:flex;"><span>Case (upper, lower): upper
</span></span><span style="display:flex;"><span>HELLO WORLD! ALSO, HEY YOU ☺️
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(venv) $ hello sally
</span></span><span style="display:flex;"><span>Case (upper, lower): lower
</span></span><span style="display:flex;"><span>hello world! also, hey sally ☺️
</span></span></code></pre></div><p>You may also set a custom prompt string if you wish:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># helloworld.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;-c&#39;</span>, <span style="font-style:italic">&#39;--case&#39;</span>,
</span></span><span style="display:flex;"><span>              type=click.Choice([<span style="font-style:italic">&#39;upper&#39;</span>, <span style="font-style:italic">&#39;lower&#39;</span>]),
</span></span><span style="display:flex;"><span>              prompt=<span style="font-style:italic">&#39;Please enter case&#39;</span>)
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;person&#39;</span>, default=<span style="font-style:italic">&#39;you&#39;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello(<span style="font-weight:bold">case</span>, person):
</span></span><span style="display:flex;"><span>    response = <span style="font-style:italic">&#34;Hello World! Also, hey </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic"> ☺️&#34;</span>.format(person)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;upper&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.upper())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">elif</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;lower&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.lower())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        click.echo(response)
</span></span></code></pre></div><p>The set string will now be displayed instead of the default prompt:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello
</span></span><span style="display:flex;"><span>Please enter <span style="font-weight:bold">case</span> (upper, lower): upper
</span></span><span style="display:flex;"><span>HELLO WORLD! ALSO, HEY YOU ☺️
</span></span></code></pre></div>]]></description></item><item><title>Adding arguments to CLI commands</title><link>https://wangonya.com/blog/click-commands-arguments/</link><pubDate>Fri, 09 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/click-commands-arguments/</guid><description><![CDATA[<p>Arguments work very similarly to
<a href="https://wangonya.com/blog/click-commands-options/">options</a>. If you&rsquo;re
familiar with functional programming, then you&rsquo;re familiar with
arguments. The concept is the same in Click.</p>
<p>Let&rsquo;s edit our code a bit to see how we can integrate arguments.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># helloworld.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;-c&#39;</span>, <span style="font-style:italic">&#39;--case&#39;</span>, type=click.Choice([<span style="font-style:italic">&#39;upper&#39;</span>, <span style="font-style:italic">&#39;lower&#39;</span>]))
</span></span><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;person&#39;</span>, default=<span style="font-style:italic">&#39;you&#39;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello(<span style="font-weight:bold">case</span>, person):
</span></span><span style="display:flex;"><span>    response = <span style="font-style:italic">&#34;Hello World! Also, hey </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic"> ☺️&#34;</span>.format(person)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;upper&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.upper())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">elif</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;lower&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.lower())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        click.echo(response)
</span></span></code></pre></div><p>Just like with commands and options, Click provides a decorator to add
arguments.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>@click.argument(<span style="font-style:italic">&#39;person&#39;</span>, default=<span style="font-style:italic">&#39;you&#39;</span>)
</span></span></code></pre></div><p>We specify that <code>hello()</code> should expect an argument
<code>person</code> to be passed in when it&rsquo;s called, and add a default
value so that it&rsquo;s ok to call the command without passing in the
argument.</p>
<p>Saving and running the app gives the following results:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello  <span style="font-style:italic"># no argument - default will be used</span>
</span></span><span style="display:flex;"><span>Hello World! Also, hey you ☺️
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(venv) $ hello Meg  <span style="font-style:italic"># Meg is the argument</span>
</span></span><span style="display:flex;"><span>Hello World! Also, hey Meg ☺️
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(venv) $ hello chris -c upper   <span style="font-style:italic"># combining arguments with options</span>
</span></span><span style="display:flex;"><span>HELLO WORLD! ALSO, HEY CHRIS ☺️
</span></span></code></pre></div><p>With options and arguments, you can add a lot of functionality to a
single command.</p>
]]></description></item><item><title>Adding options to CLI commands</title><link>https://wangonya.com/blog/click-commands-options/</link><pubDate>Wed, 07 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/click-commands-options/</guid><description><![CDATA[<p>In the previous post, we used <code>setuptools</code> to package our app
and enable us to run it using a single executable command
<code>hello</code>. In this post, we look at how to make CLI apps more
functional and interactive using options.</p>
<h2 id="options">Options</h2>
<p>Options are used to alter the default behavior of commands. This is
often accomplished by passing in parameters in the form of
<code>--option</code> or <code>-o</code> for short.</p>
<p>Let&rsquo;s assume that instead of just printing out &quot;Hello World!&quot;, we
wanted to have the option of printing it in all lowercase characters or
all uppercase characters. We can add this functionality by adding an
<code>option()</code> decorator.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># helloworld.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;-c&#39;</span>, <span style="font-style:italic">&#39;--case&#39;</span>, type=click.Choice([<span style="font-style:italic">&#39;upper&#39;</span>, <span style="font-style:italic">&#39;lower&#39;</span>]))
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello(<span style="font-weight:bold">case</span>):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">case</span>:
</span></span><span style="display:flex;"><span>        click.echo(<span style="font-style:italic">&#39;You selected </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic"> case.&#39;</span>.format(<span style="font-weight:bold">case</span>))
</span></span><span style="display:flex;"><span>    <span style="font-style:italic"># click.echo(&#39;Hello World!&#39;)</span>
</span></span></code></pre></div><p>Then run the app, passing in the created option:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello -c upper  <span style="font-style:italic"># --case would also work</span>
</span></span><span style="display:flex;"><span>You selected upper <span style="font-weight:bold">case</span>.
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello -c lower
</span></span><span style="display:flex;"><span>You selected lower <span style="font-weight:bold">case</span>.
</span></span></code></pre></div><p>Now try passing in some other option, like &quot;normal&quot;:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello -c normal
</span></span><span style="display:flex;"><span>Usage: hello [OPTIONS]
</span></span><span style="display:flex;"><span>Try <span style="font-style:italic">&#34;hello --help&#34;</span> <span style="font-weight:bold">for</span> help.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Error: Invalid value <span style="font-weight:bold">for</span> <span style="font-style:italic">&#34;-c&#34;</span> / <span style="font-style:italic">&#34;--case&#34;</span>: invalid choice: normal. (choose from upper, lower)
</span></span></code></pre></div><p>It gives us an error: <code>invalid choice: normal</code> and even
guides us on the options to choose from
<code>(choose from upper, lower)</code>, since that&rsquo;s what we specified
<code>type=click.Choice(['upper', 'lower'])</code>. Error handling on
that part is handled by default.</p>
<p>Ok, now that the option is passed in successfully, we can add in the
logic to see our desired output.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span>@click.option(<span style="font-style:italic">&#39;-c&#39;</span>, <span style="font-style:italic">&#39;--case&#39;</span>, type=click.Choice([<span style="font-style:italic">&#39;upper&#39;</span>, <span style="font-style:italic">&#39;lower&#39;</span>]))
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello(<span style="font-weight:bold">case</span>):
</span></span><span style="display:flex;"><span>    response = <span style="font-style:italic">&#34;Hello World!&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;upper&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.upper())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">elif</span> <span style="font-weight:bold">case</span> == <span style="font-style:italic">&#39;lower&#39;</span>:
</span></span><span style="display:flex;"><span>        click.echo(response.lower())
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        click.echo(response)
</span></span></code></pre></div><p>All we&rsquo;ve done is add an <code>if-else</code> to check the option
passed in, and return the text in either upper case, lower case, or just
normal. Now when we install our app again and run it, we get these
results:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello
</span></span><span style="display:flex;"><span>Hello World!
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(venv) $ hello -c upper
</span></span><span style="display:flex;"><span>HELLO WORLD!
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>(venv) $ hello -c lower
</span></span><span style="display:flex;"><span>hello world!
</span></span></code></pre></div><p>In the next post, we&rsquo;ll enhance our command even more by adding
arguments.</p>
]]></description></item><item><title>Using setuptools to package your Python app</title><link>https://wangonya.com/blog/using-setuptools/</link><pubDate>Mon, 05 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/using-setuptools/</guid><description><![CDATA[<p>In our previous post, we made a Hello World! app to get us started with
Click. You might have noticed though that we needed to do
<code>python hello-world.py</code> to run it. Since we&rsquo;re building CLI
apps, that&rsquo;s just not cool and it&rsquo;s not how CLI apps work anyway. We
need to be able to run a single command, something like:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello
</span></span><span style="display:flex;"><span>Hello World!
</span></span></code></pre></div><p>That&rsquo;s where <a href="https://setuptools.readthedocs.io/en/latest/">setuptools</a>
comes in. Setuptools helps us bundle our script so we can install it and
run it like an app (<code>$ hello</code>), instead of like a script
(<code>$ python hello-world.py</code>).</p>
<blockquote>
<p>Setuptools is a collection of enhancements to the Python distutils
that allow developers to more easily build and distribute Python
packages, especially ones that have dependencies on other packages. -
Docs</p>
</blockquote>
<p>The first thing we&rsquo;ll need to do is add a new file to our project and
call it <code>setup.py</code>. We&rsquo;ll also rename
<code>hello-world.py</code> to <code>helloworld.py</code> (remove the
dash). I&rsquo;ll explain why this is necessary when we get to the
<code>setup()</code> section. Our project structure should now look like
this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>hello-world-cli
</span></span><span style="display:flex;"><span>    |- helloworld.py  <span style="font-style:italic"># renamed from hello-world.py</span>
</span></span><span style="display:flex;"><span>    |- setup.py  <span style="font-style:italic"># new file</span>
</span></span></code></pre></div><p>In the <code>helloworld.py</code>, remove the <code>if __name__ == '__main__':</code> section. The code should now look
like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello():
</span></span><span style="display:flex;"><span>    click.echo(<span style="font-style:italic">&#39;Hello World!&#39;</span>)
</span></span></code></pre></div><p>In the <code>setup.py</code> file, add this code:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">setuptools</span> <span style="font-weight:bold">import</span> setup
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>setup(
</span></span><span style="display:flex;"><span>    name=<span style="font-style:italic">&#39;hello-world-cli&#39;</span>,
</span></span><span style="display:flex;"><span>    py_modules=[<span style="font-style:italic">&#39;helloworld&#39;</span>],
</span></span><span style="display:flex;"><span>    install_requires=[
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#39;Click&#39;</span>,
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    entry_points=<span style="font-style:italic">&#39;&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        [console_scripts]
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">        hello=helloworld:hello
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">    &#39;&#39;&#39;</span>,
</span></span><span style="display:flex;"><span>)
</span></span></code></pre></div><p>Let&rsquo;s examine what each line of code does.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">setuptools</span> <span style="font-weight:bold">import</span> setup
</span></span></code></pre></div><p>We need to import <code>setup</code> from <code>setuptools</code> in
order to use it.</p>
<p>Next, we call the <code>setup()</code> function and pass in a number of
parameters:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>name=<span style="font-style:italic">&#39;hello-world-cli&#39;</span>
</span></span></code></pre></div><p>This&rsquo;ll be the name of our CLI app.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>py_modules=[<span style="font-style:italic">&#39;helloworld&#39;</span>]
</span></span></code></pre></div><p>This tells the <code>setup()</code> where to find our main module to
execute. Our main file here is <code>helloworld.py</code> so we set
<code>helloworld</code> as the module. We can keep it that simple since
we only have one file for now, but as our app grows we&rsquo;ll replace
<code>py_modules</code> with <code>packages=find_packages()</code>. More
on that later.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>install_requires=[<span style="font-style:italic">&#39;Click&#39;</span>]
</span></span></code></pre></div><p>Our app has Click as a dependency, so it needs to be installed for it to
work. <code>setup()</code> needs to know about this so it can include it
as it packages our project. <code>install_requires</code> accepts a list
of values, so if we had more dependencies, we would list all of them
here.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>entry_points=<span style="font-style:italic">&#39;&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">          [console_scripts]
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">          hello=helloworld:hello
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">      &#39;&#39;&#39;</span>
</span></span></code></pre></div><p>This is the part that saves us the hassle of having to run the app with
<code>python ...</code> every time, and enables us to just execute
<code>hello</code> to run it.</p>
<p>It&rsquo;s important to note that if we maintained our previous name
(<code>hello-world.py</code>), the <code>setup</code> would have failed
at <code>entry_points</code>. This is because python module names
shouldn&rsquo;t have dashes.</p>
<p>We can now install our app in our environment and run it. To install it,
run:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ pip install --editable .
</span></span></code></pre></div><p>Then execute the created command:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ hello
</span></span><span style="display:flex;"><span>Hello World!
</span></span></code></pre></div>]]></description></item><item><title>Setting up your Python environment for Click</title><link>https://wangonya.com/blog/setting-up-python-click/</link><pubDate>Fri, 02 Aug 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/setting-up-python-click/</guid><description><![CDATA[<p>In this post, we&rsquo;ll cover the very basics of working with Python and
Click to create a CLI app. We&rsquo;ll install Python 3, set up our
development environment, install Click, and create a
<code>hello-world</code> app.</p>
<h3 id="python-3x">Python 3.x</h3>
<p>Getting started with Python is easy. Most *nix systems come with Python
pre-installed. We&rsquo;ll be using Python 3. To check which version of
Python you have, open up your terminal and run <code>python -V</code>.
You should get an output similar to this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>Python 2.7.10
</span></span></code></pre></div><p>This means the default Python version installed on my computer is
<code>2.7.10</code>. Most Macs ship with Python 2 by default. If you got
a <code>3.x.x</code>, then you&rsquo;re good to go. After installing Python
3, running <code>python3 -V</code> outputs:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>Python 3.7.3
</span></span></code></pre></div><p>If you don&rsquo;t have Python installed, you can head over to
<a href="https://www.python.org/downloads/">python.org</a>, download the
appropriate installer for your system, and run it. This step is
necessary if you&rsquo;re on Windows.</p>
<h3 id="pip">pip</h3>
<p><code>pip</code> is a package manager for Python. It allows us to
install libraries and dependencies that we&rsquo;ll need to use for our
project. It comes pre-installed with Python. To check if you have it,
you can run <code>pip -V</code> or <code>pip3 -V</code>. You should see
something like:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>pip 19.0.3 from /usr/local/lib/python3.7/site-packages/pip (python 3.7)
</span></span></code></pre></div><h3 id="virtualenv">Virtualenv</h3>
<p>When working on your Python projects, it&rsquo;s always a good idea to create
isolated environments to work in. This is because different projects
will require different dependencies or different versions of those
dependencies. Installing these globally will be hard to manage and will
just mess up your system. Installing them in a project&rsquo;s environment
keeps things clean. There&rsquo;s a couple of options to deal with
environments in Python but we&rsquo;ll focus on <code>virtualenv</code>.</p>
<p>We&rsquo;re going to create a new directory and create a virtual environment
in it. On your terminal, run:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ mkdir hello-world-cli &amp;&amp; cd hello-world-cli
</span></span></code></pre></div><p>The command above creates a new directory called
<code>hello-world-cli</code> and enters that directory.</p>
<p>Next, we&rsquo;ll install <code>virtualenv</code> using <code>pip</code> and
create our virtual environment.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ pip3 install virtualenv
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ virtualenv venv
</span></span></code></pre></div><p>We now have a Python virtual environment in our directory. To use it, we
need to activate it by running:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ source venv/bin/activate
</span></span><span style="display:flex;"><span>(venv) $
</span></span></code></pre></div><p>You&rsquo;ll notice the change in your terminal prompt when the environment
is activated. The environment name is prefixed at the prompt. That&rsquo;s
how you know you&rsquo;re working in the environment.</p>
<h3 id="click">Click</h3>
<p>Now that we have our environment ready, we can start working on our
project. Python provides <a href="https://docs.python-guide.org/scenarios/cli/">a number of
packages</a> to help in
creating CLI apps. We&rsquo;ll be using
<a href="https://click.palletsprojects.com/en/7.x/">Click</a>, so we need to
install it to get started.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ pip install Click
</span></span></code></pre></div><p>That&rsquo;s all we need to get started.</p>
<h3 id="hello-world">Hello World!</h3>
<p>As usual, we&rsquo;ll start off with a &quot;Hello World!&quot; program.</p>
<p>Still in the <code>hello-world-cli</code> directory, create a file
called <code>hello-world.py</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ touch hello-world.py
</span></span></code></pre></div><p>Open the file in your preferred text editor and add this code:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@click.command()
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello():
</span></span><span style="display:flex;"><span>    click.echo(<span style="font-style:italic">&#39;Hello World!&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> __name__ == <span style="font-style:italic">&#39;__main__&#39;</span>:
</span></span><span style="display:flex;"><span>    hello()
</span></span></code></pre></div><p>Let&rsquo;s examine what&rsquo;s happening at each line.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">click</span>
</span></span></code></pre></div><p>Here, we import <code>click</code> so we can use it to create our
commands.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>@click.command()
</span></span></code></pre></div><p>Whenever you see something on top of a function with an <code>@</code>
symbol in Python, that&rsquo;s a decorator. Without going into a lot of
details on decorators, it&rsquo;s enough to understand (for now) that they
simply modify the behavior of the functions they &quot;decorate&quot;. Click
uses the concept of decorators to convert Python functions into commands
that can be directly executed through the terminal. The decorator here
converts <code>hello()</code> into a command. We&rsquo;ll learn more about
commands later.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello():
</span></span></code></pre></div><p>This is how we define functions in Python.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>click.echo(<span style="font-style:italic">&#39;Hello World!&#39;</span>)
</span></span></code></pre></div><p>Calling <code>hello()</code> will run
<code>click.echo('Hello World!')</code> which displays the text &quot;Hello
World!&quot; on the terminal.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">if</span> __name__ == <span style="font-style:italic">&#39;__main__&#39;</span>:
</span></span></code></pre></div><p>This is the main entry point of our script.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>hello()
</span></span></code></pre></div><p>This invokes our function/command.</p>
<p>Ok, time to see the results. Save the file, go back to the terminal, and
run the program:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>(venv) $ python hello-world.py
</span></span><span style="display:flex;"><span>Hello World!
</span></span></code></pre></div>]]></description></item><item><title>Fibonacci sequence with Python recursion and memoization</title><link>https://wangonya.com/blog/python-fibonacci-recursion-memoization/</link><pubDate>Sun, 16 Jun 2019 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/python-fibonacci-recursion-memoization/</guid><description><![CDATA[<p>The Fibonacci sequence is a sequence of numbers such that any number,
except for the first and second, is the sum of the previous two.</p>
<p>For example:</p>
<pre tabindex="0"><code class="language-example" data-lang="example">[0, 1, 1, 2, 3, 5, 8, 13, 21...]
</code></pre><p>We can represent this in the formula:</p>
<pre tabindex="0"><code class="language-example" data-lang="example">fib(n) = fib(n-1)+fib(n-2)
</code></pre><p>With this formula, we can write a simple <a href="http://pages.cs.wisc.edu/~calvin/cs110/RECURSION.html">recursive
function</a> to
solve for <code>fib(n)</code>.</p>
<p><strong>Note: Only use this to test for small numbers, preferably n &lt; 10.
I&rsquo;ll explain later</strong></p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> fib(n):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> n &lt; 2:  <span style="font-style:italic"># base case</span>
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> n
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> fib(n-1) + fib(n-2)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> __name__ == <span style="font-style:italic">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>  print(fib(7))
</span></span></code></pre></div><h3 id="why-do-we-need-a-base-case">Why do we need a base case?</h3>
<p>It&rsquo;s easy enough to convert the formula directly into</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> fib(n):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> fib(n-1) + fib(n-2)
</span></span></code></pre></div><p>The problem with this though is that when you run it, it throws a
<a href="https://docs.python.org/3/library/exceptions.html#RecursionError"><code>RecursionError</code></a>.
This simply means that there&rsquo;s possibly an infinite loop in the
program. A base case in a recursive function tells the function when to
stop (to avoid going into an infinite loop) and is usually something
that is already known or that can be solved for easily without needing
the function. In our case here, we know from the definition that any
number in the sequence, <strong>except for the first and second</strong>, is the sum
of the previous two. We use that to form our base case
<code>if n &lt; 2: return n</code>.</p>
<h2 id="making-it-more-efficient">Making it more efficient</h2>
<p>Remember when I told you to only test the program with small values of
<code>n</code>? Here&rsquo;s why.</p>
<p>As it stands, every call to <code>fib()</code> results in two more calls
to <code>fib()</code> in the <code>return</code> statement. The call
tree grows exponentially. 15 calls are required to compute
<code>fib(5)</code>, 177 calls for <code>fib(10)</code>, 21,891 for
<code>fib(20)</code>&hellip; you get the point. To solve this problem, we can
use
<a href="https://sites.radford.edu/~nokie/classes/360/dp-memoized.html">memoization</a>.</p>
<p>Memoization helps avoid unnecessary calculation of the same values if
they were already previously calculated. It works just like memorization
for humans. You already have <code>2 x 2</code> memorized and can give
the answer immediately without having to use a calculator.
<code>799 x 377</code>? You probably need to use a calculator for that.
If, for some reason, you find that you get asked <code>799 x 377</code>
a lot, it would be nice to have it memorized so you don&rsquo;t have to
calculate it every other time. The value of <code>799 x 377</code> will
always remain the same, so all you have to do is calculate it once, save
the value in your &quot;cache&quot; (memory), and retrieve it every time you
need it.</p>
<p>Luckily, python has a <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache">built-in
decorator</a>
that does just that.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">functools</span> <span style="font-weight:bold">import</span> lru_cache
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@lru_cache(maxsize=<span style="font-weight:bold">None</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> fib(n):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> n &lt; 2:  <span style="font-style:italic"># base case</span>
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> n
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> fib(n-1) + fib(n-2)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> __name__ == <span style="font-style:italic">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>  print(fib(50))
</span></span></code></pre></div><p>Now you can test with large numbers safely.</p>
]]></description></item><item><title>Creating a simple ToDo API with Django</title><link>https://wangonya.com/blog/django-todo-api/</link><pubDate>Mon, 01 Apr 2019 07:57:54 +0300</pubDate><guid>https://wangonya.com/blog/django-todo-api/</guid><description><![CDATA[<p>In this tutorial, we&rsquo;ll create a simple todo api with Python 3 and
Django 2.</p>
<h2 id="installing-the-requirements">Installing the requirements</h2>
<p>Create a virtual environment and install Django.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ virtualenv venv <span style="font-style:italic"># creates a virtual environment</span>
</span></span><span style="display:flex;"><span>$ source venv/bin/activate <span style="font-style:italic"># activates the virtual environment</span>
</span></span><span style="display:flex;"><span>(venv)$ pip install Django
</span></span></code></pre></div><p>That&rsquo;s all we&rsquo;ll need for now.</p>
<h2 id="creating-the-project">Creating the project</h2>
<p>Use the Django <code>startproject</code> command to create the project
we&rsquo;ll be working on.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ django-admin startproject todoapi
</span></span></code></pre></div><p>This creates a <code>todoapi</code> directory with generated files to
start us off. The directory should look something like this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>manage.py
</span></span><span style="display:flex;"><span>todoapi/
</span></span><span style="display:flex;"><span>    __init__.py
</span></span><span style="display:flex;"><span>    settings.py
</span></span><span style="display:flex;"><span>    urls.py
</span></span><span style="display:flex;"><span>    wsgi.py
</span></span></code></pre></div><h2 id="database-setup">Database setup</h2>
<p>To keep things simple, we&rsquo;ll use the SQlite database, so we don&rsquo;t have
to install anything since it comes with Python. In addition, that&rsquo;s
already setup for us in <code>todoapi/settings.py</code>. Have a look at
the code and you should see something similar to this:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># Database</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># https://docs.djangoproject.com/en/2.1/ref/settings/#databases</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DATABASES = {
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#39;default&#39;</span>: {
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#39;ENGINE&#39;</span>: <span style="font-style:italic">&#39;django.db.backends.sqlite3&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#39;NAME&#39;</span>: os.path.join(BASE_DIR, <span style="font-style:italic">&#39;db.sqlite3&#39;</span>),
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="creating-models">Creating models</h2>
<p>To create models for our database, we first need to create a todos
&quot;app&quot;. This is where we&rsquo;ll implement our features.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ python manage.py startapp todos
</span></span></code></pre></div><p>This will create a <code>todos</code> directory with the following
files:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>migrations/
</span></span><span style="display:flex;"><span>    __init__.py
</span></span><span style="display:flex;"><span>__init__.py
</span></span><span style="display:flex;"><span>admin.py
</span></span><span style="display:flex;"><span>apps.py
</span></span><span style="display:flex;"><span>models.py
</span></span><span style="display:flex;"><span>tests.py
</span></span><span style="display:flex;"><span>views.py
</span></span></code></pre></div><p>This app should be added to the <code>todoapi/settings.py</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>INSTALLED_APPS = [
</span></span><span style="display:flex;"><span>    ...,
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#39;todos&#39;</span>
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><p>Ok, now that Django knows about our app, open the <code>models.py</code>
file to add the models. We&rsquo;ll only create one model called
<code>Todo</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.db</span> <span style="font-weight:bold">import</span> models
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Create your models here.</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">class</span> <span style="font-weight:bold">Todo</span>(models.Model):
</span></span><span style="display:flex;"><span>    todo = models.CharField(max_length=100, null=<span style="font-weight:bold">False</span>,
</span></span><span style="display:flex;"><span>                            help_text=<span style="font-style:italic">&#34;This field is required&#34;</span>)
</span></span><span style="display:flex;"><span>    done = models.BooleanField(default=<span style="font-weight:bold">False</span>)
</span></span></code></pre></div><p>This model will create a table for us with <code>todo</code> and
<code>done</code> columns to save our data. The <code>todo</code> column
will save the actual todo, and the <code>done</code> column will save
the status &ndash; whether it&rsquo;s done or not. Notice that it is a
<code>BooleanField</code>, meaning we&rsquo;ll save <code>True</code> when
done or <code>False</code> when not done, which is the default.</p>
<p>Now all we need to do is run <code>makemigrations</code> to notify
Django of our models, and <code>migrate</code> to do the actual
migration.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ python manage.py makemigrations todos
</span></span><span style="display:flex;"><span>$ python manage.py migrate
</span></span></code></pre></div><h2 id="creating-the-endpoints">Creating the endpoints</h2>
<p>We&rsquo;ll have two endpoints for now:</p>
<ul>
<li><code>/todos</code> to <code>GET</code> a list of all our todos</li>
<li><code>/todos/&lt;id&gt;</code> to <code>GET</code> the todo matching the
id</li>
</ul>
<p>To test this out, we&rsquo;ll create two simple views in the
<code>todos/view.py</code> file.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.http</span> <span style="font-weight:bold">import</span> JsonResponse
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.shortcuts</span> <span style="font-weight:bold">import</span> get_object_or_404
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">.models</span> <span style="font-weight:bold">import</span> Todo
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Create your views here.</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> todos(request):
</span></span><span style="display:flex;"><span>    todos_list = Todo.objects.all()
</span></span><span style="display:flex;"><span>    data = {
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#34;todos&#34;</span>: list(todos_list.values(
</span></span><span style="display:flex;"><span>            <span style="font-style:italic">&#34;todo&#34;</span>, <span style="font-style:italic">&#34;done&#34;</span>
</span></span><span style="display:flex;"><span>        ))
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> JsonResponse(data)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> single_todo(request, pk):
</span></span><span style="display:flex;"><span>    todo = get_object_or_404(Todo, pk=pk)
</span></span><span style="display:flex;"><span>    data = {
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#34;todo&#34;</span>: todo.todo,
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#34;done&#34;</span>: todo.done
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> JsonResponse(data)
</span></span></code></pre></div><p>Create a new file called <code>urls.py</code> in your <code>todos</code>
app and add the following code:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># todos/urls.py</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.urls</span> <span style="font-weight:bold">import</span> path
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">.views</span> <span style="font-weight:bold">import</span> todos, single_todo
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>urlpatterns = [
</span></span><span style="display:flex;"><span>    path(<span style="font-style:italic">&#34;todos/&#34;</span>, todos, name=<span style="font-style:italic">&#34;todos&#34;</span>),
</span></span><span style="display:flex;"><span>    path(<span style="font-style:italic">&#34;todos/&lt;int:pk&gt;&#34;</span>, single_todo, name=<span style="font-style:italic">&#34;single_todo&#34;</span>)
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><p>Go to <code>todoapi/urls.py</code> and include the todos url you just
created:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># todoapi/urls.py</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.contrib</span> <span style="font-weight:bold">import</span> admin
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.urls</span> <span style="font-weight:bold">import</span> path, include  <span style="font-style:italic"># add include here</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>urlpatterns = [
</span></span><span style="display:flex;"><span>    path(<span style="font-style:italic">&#39;admin/&#39;</span>, admin.site.urls),
</span></span><span style="display:flex;"><span>    path(<span style="font-style:italic">&#39;&#39;</span>, include(<span style="font-style:italic">&#39;todos.urls&#39;</span>))  <span style="font-style:italic"># add this</span>
</span></span><span style="display:flex;"><span>]
</span></span></code></pre></div><h2 id="set-up-your-admin-and-test-the-endpoints">Set up your admin and test the endpoints</h2>
<p>Create a superuser:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>$ python manage.py createsuperuser
</span></span></code></pre></div><p>Next, register your models in the <code>/todos/admin.py</code> file so
you can have access to them from the admin dashboard:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">django.contrib</span> <span style="font-weight:bold">import</span> admin
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">.models</span> <span style="font-weight:bold">import</span> Todo
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Register your models here.</span>
</span></span><span style="display:flex;"><span>admin.site.register(Todo)
</span></span></code></pre></div><p>That&rsquo;s it! Now run the server and go to
<code>http://127.0.0.1:8000/admin</code>. Log in with the details you
registered for the superuser above to add your todos.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/x6voqtudx91zc4mnvede.png" alt="dj-admin">
</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/pmorh3sdlnknzfo1h2c2.png" alt="dj-add">
</p>
<p>You can retrieve the todos created via a rest client via the endpoints</p>
<ul>
<li><code>http://127.0.0.1:8000/todos</code></li>
<li><code>http://127.0.0.1:8000/todos/&lt;id&gt;</code></li>
</ul>
]]></description></item><item><title>Caring for your health as a developer</title><link>https://wangonya.com/blog/health-dev/</link><pubDate>Thu, 14 Mar 2019 19:54:39 +0300</pubDate><guid>https://wangonya.com/blog/health-dev/</guid><description><![CDATA[<blockquote>
<p>&quot;When health is absent, wisdom cannot reveal itself, art cannot
manifest, strength cannot fight, wealth becomes useless, and
intelligence cannot be applied.&quot; ― Herophilus</p>
</blockquote>
<p>Let&rsquo;s face it. As developers, it&rsquo;s easy to let things get a bit out of
hand when it comes to health. Many times we find ourselves in front of screens for
hours on end. We sleep really late (or not at all) sometimes. Unless
you&rsquo;re disciplined enough to follow a schedule, you might find yourself
not having time to eat proper meals so snacking becomes a habit. All
these are usually sacrifices made to fix some bug or find the most
efficient solution to some problem. Usually, our health suffers as a
result. While this might seem to work out just fine for the moment, we
don&rsquo;t look at the bigger picture - how it will affect us in the future.</p>
<p>I think, if healthier practices were adopted, developers would be much
more productive and would be able to accomplish some tasks in less time
simply because the brain is much clearer. I could cite surveys and research here to prove this point, but simple personal experience
will suffice. It&rsquo;s hard enough to get anything done when you&rsquo;re down
with a cold. There is an intimate connection between the mind and the
body, and when one suffers, the other no doubt feels it. Below are some
points to watch out for if you&rsquo;re looking to keep fit physically and
mentally.</p>
<h2 id="watch-what-you-eat-">Watch what you eat 🥘</h2>
<p>Just like your car wouldn&rsquo;t run without the correct fuel, our bodies
also need the right fuel to work efficiently. Make sure you find time to
eat a properly balanced meal - preferably a big breakfast to give you
enough energy for the day, a good lunch, and a light supper. This is, of
course, assuming a regular daytime 9 to 5 type of schedule. When working
odd hours, you can adjust accordingly.</p>
<h2 id="have-some-exercise-">Have some exercise 🏃🏽‍♂️</h2>
<p>I won&rsquo;t go as far as some have to say that <a href="https://edition.cnn.com/2017/09/11/health/sitting-increases-risk-of-death-study/index.html">sitting
kills</a>
😄 but it&rsquo;s definitely a good idea to wake up and stretch at least once
or twice every hour. The Pomodoro technique is great for this because
you can take your breaks to get off your chair for five minutes. I have
found that taking walks is a great way to refresh your mind especially
when you&rsquo;re struggling with something. You can also take advantage of
the fresh air of early morning jogs.</p>
<h2 id="stay-hydrated-">Stay hydrated 💧</h2>
<p>If you wait until you feel thirsty, you&rsquo;ve waited too long.</p>
<h2 id="take-a-break-">Take a break 🚶</h2>
<p><img src="https://i.redd.it/mdjsol1eiad11.jpg" alt="debug">
</p>
<p>We&rsquo;ve all been there. Sometimes our minds work best when we step away
from it all and take a break. Again, taking walks work great! I took a
course on Coursera some time back called &quot;Learning How to Learn&quot; that
explains the science behind how this works. You can <a href="https://www.coursera.org/lecture/learning-how-to-learn/introduction-to-the-focused-and-diffuse-modes-75EsZ">check it
out</a>.</p>
<h2 id="get-enough-sleep-">Get enough sleep 🛌💤</h2>
<p>According to <a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3880190/">this
study</a>, sleep
helps clear the brain of toxins that build up while we are awake.
Depriving yourself of sleep only builds up these toxins and your brain
gets all foggy. This only leads to spending more hours trying to figure
something out, which leads to more sleep deprivation, and it becomes a
vicious cycle. Everyone needs different amounts of sleep but if you can
clock in 7 or 8 hours, that should be enough. Again, this assumes a
regular daytime 9 to 5 type of schedule. I understand that some people
find it easier to work late at night and that&rsquo;s cool. I&rsquo;m a morning
person myself so I&rsquo;d rather sleep early and rise early.</p>
<p>I might get into more details on each of these steps in future posts in
the series. Topics of interest include taking a closer look at coffee
and energy drinks to see if they really make us more productive.</p>
]]></description></item><item><title>Lexical variable scoping with Javascript</title><link>https://wangonya.com/blog/lexical-scoping/</link><pubDate>Fri, 08 Mar 2019 12:52:10 +0300</pubDate><guid>https://wangonya.com/blog/lexical-scoping/</guid><description><![CDATA[<p>Lexical scoping means that the scope of a variable is determined by where it is defined in the source code — specifically, by the block or function it is written inside. In Javascript, code blocks are created using curly braces ({}). For
example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">function</span> someFunction() {
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">// some code here
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> anotherFunction() {
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">// some more code here
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>someFunction</code> and <code>anotherFunction</code> are two
different code blocks. These two different code blocks could also be
considered as two different scopes. What that means is that the
variables declared in <code>someFunction</code> only affect that block
of code, and those declared in <code>anotherFunction</code> only affect
that block of code. They are <em>&quot;scoped&quot;</em> in that sense.</p>
<p>To illustrate:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kenny&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> someFunction() {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kyle&#34;</span>
</span></span><span style="display:flex;"><span>    console.log(<span style="font-style:italic">&#34;someFunction block:&#34;</span>, name) <span style="font-style:italic">// someFunction block: Kyle
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> anotherFunction() {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Timmy&#34;</span>
</span></span><span style="display:flex;"><span>    console.log(<span style="font-style:italic">&#34;anotherFunction block:&#34;</span>, name) <span style="font-style:italic">// anotherFunction block: Timmy
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(<span style="font-style:italic">&#34;global&#34;</span>, name) <span style="font-style:italic">// global Kenny
</span></span></span></code></pre></div><p>As you can see, the same variable <code>name</code> retains its global
value although it gets redefined within <code>someFunction</code> and
<code>anotherFunction</code>.</p>
<p>Now here is where it can get a bit tricky. With that knowledge in mind,
it is easy to assume that this would always be the case whenever we have
code blocks. Except, it doesn&rsquo;t work the same with <code>if/else</code>
statements and <code>for</code> loops.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kenny&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> (name) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kyle&#34;</span>;
</span></span><span style="display:flex;"><span>  console.log(<span style="font-style:italic">&#34;if block:&#34;</span>, name); <span style="font-style:italic">// if block: Kyle
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(<span style="font-style:italic">&#34;global&#34;</span>, name); <span style="font-style:italic">// global Kyle
</span></span></span></code></pre></div><p>The <code>name</code> variable inside the <code>if</code> block resets
the value of <code>name</code>. The same happens in a <code>for</code>
loop:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kenny&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> (<span style="font-weight:bold">var</span> i = 0; i &lt; 1; i++) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kyle&#34;</span>;
</span></span><span style="display:flex;"><span>  console.log(<span style="font-style:italic">&#34;for loop block:&#34;</span>, name); <span style="font-style:italic">// for loop block: Kyle
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(<span style="font-style:italic">&#34;global&#34;</span>, name); <span style="font-style:italic">// global Kyle
</span></span></span></code></pre></div><p>The solution is to use the <code>let</code> keyword instead of
<code>var</code>.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kenny&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">if</span> (name) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> name = <span style="font-style:italic">&#34;Kyle&#34;</span>;
</span></span><span style="display:flex;"><span>  console.log(<span style="font-style:italic">&#34;if block:&#34;</span>, name); <span style="font-style:italic">// if block: Kyle
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(<span style="font-style:italic">&#34;global&#34;</span>, name); <span style="font-style:italic">// global Kenny
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">var</span> name = <span style="font-style:italic">&#34;Kenny&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">for</span> (<span style="font-weight:bold">var</span> i = 0; i &lt; 1; i++) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> name = <span style="font-style:italic">&#34;Kyle&#34;</span>;
</span></span><span style="display:flex;"><span>  console.log(<span style="font-style:italic">&#34;for loop block:&#34;</span>, name); <span style="font-style:italic">// for loop block: Kyle
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(<span style="font-style:italic">&#34;global&#34;</span>, name); <span style="font-style:italic">// global Kenny
</span></span></span></code></pre></div>]]></description></item><item><title>Javascript arithmetic cheat sheet</title><link>https://wangonya.com/blog/js-math/</link><pubDate>Tue, 05 Mar 2019 05:25:12 +0300</pubDate><guid>https://wangonya.com/blog/js-math/</guid><description><![CDATA[<p>Given that one of the main reasons computers were invented was to solve
mathematical problems quickly, it is no wonder that all the modern
programming languages are so rich in arithmetic-oriented methods. The
earliest computers were basically just calculators. (<em>Yes, I&rsquo;m looking
at you <a href="https://en.wikipedia.org/wiki/Abacus">Abacus</a></em>). If you dabble
in Javascript (and a little math every now and then), you might find
this useful. The very obvious operations like simple addition (+) and
subtraction (-) have been omitted. So have more advanced operations.</p>
<h2 id="working-with-constants">Working with constants</h2>
<p>Logarithm to base <em>e</em></p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.E; <span style="font-style:italic">// 2.718281828459045
</span></span></span></code></pre></div><p>Logarithm to base 10</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.LN10; <span style="font-style:italic">// 2.302585092994046
</span></span></span></code></pre></div><p>Logarithm to base 2</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.LN2; <span style="font-style:italic">// 0.6931471805599453
</span></span></span></code></pre></div><p>Base 10 logarithm of <em>e</em></p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.LOG10E; <span style="font-style:italic">// 0.4342944819032518
</span></span></span></code></pre></div><p>Base 2 logarithm of <em>e</em></p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.LOG2E; <span style="font-style:italic">// 1.4426950408889634
</span></span></span></code></pre></div><p>🥧</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.PI; <span style="font-style:italic">// 3.141592653589793
</span></span></span></code></pre></div><p>Square root of 1/2</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.SQRT1_2; <span style="font-style:italic">// 0.7071067811865476
</span></span></span></code></pre></div><p>Square root of 2</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.SQRT2; <span style="font-style:italic">// 1.4142135623730951
</span></span></span></code></pre></div><p>Infinity</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">Infinity</span>; <span style="font-style:italic">// Infinity
</span></span></span></code></pre></div><h2 id="rounding">Rounding</h2>
<p><code>Math.round</code> returns the value of a number rounded to the
nearest integer.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.round(4.2); <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>Math.round(4.7); <span style="font-style:italic">// 5
</span></span></span><span style="display:flex;"><span>Math.round(4.5); <span style="font-style:italic">// 5. Half-way values are always rounded up
</span></span></span></code></pre></div><p>Speaking of rounding up, <code>Math.ceil()</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.ceil(4.2); <span style="font-style:italic">// 5
</span></span></span><span style="display:flex;"><span>Math.ceil(4.7); <span style="font-style:italic">// 5
</span></span></span><span style="display:flex;"><span>Math.ceil(-4.7); <span style="font-style:italic">// -4. Ceiling a negative number will round towards zero
</span></span></span></code></pre></div><p><code>Math.floor()</code> rounds down:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.floor(4.2); <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>Math.floor(4.7); <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>Math.floor(-4.7); <span style="font-style:italic">// -5. Flooring a negative number will round away from zero
</span></span></span></code></pre></div><h2 id="modulus-">Modulus (%)</h2>
<p>Returns the remainder after (integer) division.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>42 % 10; <span style="font-style:italic">// 2
</span></span></span><span style="display:flex;"><span>-40 % 10; <span style="font-style:italic">// -0 🤔
</span></span></span></code></pre></div><h2 id="trigonometry">Trigonometry</h2>
<p>Sine</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.sin(60); <span style="font-style:italic">// -0.3048106211022167
</span></span></span></code></pre></div><p>Cosine</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.cos(60); <span style="font-style:italic">// -0.9524129804151563
</span></span></span></code></pre></div><p>Tangent</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.tan(60); <span style="font-style:italic">// 0.320040389379563
</span></span></span></code></pre></div><h2 id="incrementing-">Incrementing (++)</h2>
<p><code>++</code> increments its operand by 1.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// postfix: returns the value before incrementing
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> a = 4, <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>  b = a++, <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>  c = a; <span style="font-style:italic">//5
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// prefix: returns the value after incrementing
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> a = 4, <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>  b = ++a, <span style="font-style:italic">// 5
</span></span></span><span style="display:flex;"><span>  c = a; <span style="font-style:italic">//5
</span></span></span></code></pre></div><h2 id="decrementing-">Decrementing (&ndash;)</h2>
<p><code>--</code> decrements its operand by 1.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// postfix: returns the value before decrementing
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> a = 4, <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>  b = a--, <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>  c = a; <span style="font-style:italic">//3
</span></span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// prefix: returns the value after decrementing
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> a = 4, <span style="font-style:italic">// 4
</span></span></span><span style="display:flex;"><span>  b = --a, <span style="font-style:italic">// 3
</span></span></span><span style="display:flex;"><span>  c = a; <span style="font-style:italic">//3
</span></span></span></code></pre></div><h2 id="exponentiation-">Exponentiation (**)</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// Math.pow() or ** can be used
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> a = 4,
</span></span><span style="display:flex;"><span>  b = 2,
</span></span><span style="display:flex;"><span>  c = Math.pow(a, b), <span style="font-style:italic">// 16
</span></span></span><span style="display:flex;"><span>  d = a ** b; <span style="font-style:italic">// 16
</span></span></span></code></pre></div><h2 id="getting-maximum-and-minimum">Getting maximum and minimum</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.max(4.2, 4.7); <span style="font-style:italic">// 4.7
</span></span></span><span style="display:flex;"><span>Math.min(4.2, 4.7); <span style="font-style:italic">// 4.2
</span></span></span></code></pre></div><p>Getting maximum and minimum from an array:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> arr = [1, 2, 3, 4, 5, 6, 7, 8, 9],
</span></span><span style="display:flex;"><span>  max = Math.max(...arr), <span style="font-style:italic">// 9
</span></span></span><span style="display:flex;"><span>  min = Math.min(...arr); <span style="font-style:italic">// 1
</span></span></span></code></pre></div><h2 id="getting-roots-">Getting roots √</h2>
<p>Square Root</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.sqrt(16); <span style="font-style:italic">// 4
</span></span></span></code></pre></div><p>Cube Root</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>Math.cbrt(27); <span style="font-style:italic">// 3
</span></span></span></code></pre></div><p>To find the nth-root, use the Math.pow() function and pass in a
fractional exponent.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// This finds the 6th root of 64
</span></span></span><span style="display:flex;"><span>Math.pow(64, 1 / 6); <span style="font-style:italic">// 4
</span></span></span></code></pre></div><p>Much more complex calculations can be done by combining one or more of
these operations.</p>
]]></description></item><item><title>Difference between a Python module and a package</title><link>https://wangonya.com/blog/python-module-package/</link><pubDate>Wed, 20 Feb 2019 18:35:12 +0300</pubDate><guid>https://wangonya.com/blog/python-module-package/</guid><description><![CDATA[<h3 id="modules">Modules</h3>
<p>Modules are single Python files that can be imported. Any python file
can be a module. For example, if I have two Python files:
<code>module.py</code> and <code>hello.py</code> in the same directory:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># module.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello(name):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Hello </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>.format(name))
</span></span></code></pre></div><p>I can <code>import</code> that module in my <code>hello.py</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic">#hello.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">module</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>module.hello(<span style="font-style:italic">&#34;World!&#34;</span>) <span style="font-style:italic"># Hello World!</span>
</span></span></code></pre></div><p>The same can be done in the interpreter:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>&gt;&gt;&gt; from module import hello
</span></span><span style="display:flex;"><span>&gt;&gt;&gt; hello(<span style="font-style:italic">&#34;World!&#34;</span>) <span style="font-style:italic"># Hello World!</span>
</span></span></code></pre></div><h3 id="packages">Packages</h3>
<p>Packages are made up of multiple Python files (or modules), and can even
include libraries written in different languages like C or C++. Seeing
an <code>__init__.py</code> file in a folder typically tells you that
that folder is a Python package. The <code>__init__.py</code> doesn&rsquo;t
have to contain any code &ndash; sometimes it does &ndash; it just has to be there
for Python take that particular folder as a package.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>📁 my_package
</span></span><span style="display:flex;"><span>    |- __init__.py
</span></span><span style="display:flex;"><span>    |- module.py
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># __init__.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">from</span> <span style="font-weight:bold">my_package.module</span> <span style="font-weight:bold">import</span> hello
</span></span></code></pre></div><p>When you import <code>my_package</code> in your script, the
<code>__init__.py</code> script will be run, giving you access to all of
the functions in the package. In this case, it only gives access to the
<code>module.hello</code> function.</p>
]]></description></item><item><title>Displaying a css spinner on ajax calls with fetch api</title><link>https://wangonya.com/blog/css-fetch-spinner/</link><pubDate>Fri, 01 Feb 2019 08:18:26 +0300</pubDate><guid>https://wangonya.com/blog/css-fetch-spinner/</guid><description><![CDATA[<p>I always have to search for how to do this or refer back to my previous
code whenever I work with <code>fetch</code>. For a while, I&rsquo;ve used
the solution to
<a href="https://stackoverflow.com/questions/43792026/display-spinner-during-ajax-call-when-using-fetch-api">this</a>
SO question. It&rsquo;s a correct solution and it works great but to be
honest, I couldn&rsquo;t clearly explain that piece of code if asked. So I thought of a
simple way to do it. Here&rsquo;s how:</p>
<h2 id="setting-up-the-html">Setting up the HTML</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="font-style:italic">&lt;!-- this will fetch the data --&gt;</span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">button</span> onclick=<span style="font-style:italic">&#34;loadData()&#34;</span>&gt;Load data&lt;/<span style="font-weight:bold">button</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">&lt;!-- this will show our spinner --&gt;</span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">div</span> hidden id=<span style="font-style:italic">&#34;spinner&#34;</span>&gt;&lt;/<span style="font-weight:bold">div</span>&gt;
</span></span></code></pre></div><p>The spinner visibility is hidden by default using the built-in
<code>hidden</code> attribute. This is the element we&rsquo;ll manipulate in
order to show and hide it as desired.</p>
<h2 id="creating-the-css-spinner">Creating the CSS spinner</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-css" data-lang="css"><span style="display:flex;"><span>#<span style="font-weight:bold">spinner</span>:not([<span style="font-weight:bold">hidden</span>]) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">position</span>: <span style="font-weight:bold">fixed</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">top</span>: 0;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">left</span>: 0;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">right</span>: 0;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">bottom</span>: 0;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">display</span>: <span style="font-weight:bold">flex</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">justify-content</span>: <span style="font-weight:bold">center</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">align-items</span>: <span style="font-weight:bold">center</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>#<span style="font-weight:bold">spinner</span>::after {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">content</span>: <span style="font-style:italic">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">width</span>: 80<span style="">px</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">height</span>: 80<span style="">px</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">border</span>: 2<span style="">px</span> <span style="font-weight:bold">solid</span> #f3f3f3;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">border-top</span>: 3<span style="">px</span> <span style="font-weight:bold">solid</span> #f25a41;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">border-radius</span>: 100<span style="">%</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">will-change</span>: <span style="font-weight:bold">transform</span>;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">animation</span>: spin 1<span style="">s</span> <span style="font-weight:bold">infinite</span> <span style="font-weight:bold">linear</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@<span style="font-weight:bold">keyframes</span> <span style="font-weight:bold">spin</span> {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">from</span> {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">transform</span>: rotate(0<span style="">deg</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">to</span> {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">transform</span>: rotate(360<span style="">deg</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="getting-things-working-with-javascript">Getting things working with Javascript</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> spinner = document.getElementById(<span style="font-style:italic">&#34;spinner&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> loadData() {
</span></span><span style="display:flex;"><span>  spinner.removeAttribute(<span style="font-style:italic">&#34;hidden&#34;</span>);
</span></span><span style="display:flex;"><span>  fetch(<span style="font-style:italic">&#34;https://www.mocky.io/v2/5185415ba171ea3a00704eed?mocky-delay=5000ms&#34;</span>)
</span></span><span style="display:flex;"><span>    .then((response) =&gt; response.json())
</span></span><span style="display:flex;"><span>    .then((data) =&gt; {
</span></span><span style="display:flex;"><span>      spinner.setAttribute(<span style="font-style:italic">&#34;hidden&#34;</span>, <span style="font-style:italic">&#34;&#34;</span>);
</span></span><span style="display:flex;"><span>      console.log(data);
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>When the <code>loadData</code> function is called, it removes the
<code>hidden</code> attribute
(<code>spinner.removeAttribute('hidden')</code>). I&rsquo;ve set the delay to
5 seconds (<code>mocky-delay=5000ms</code>) so we can see the spinner in
action. After that, the <code>hidden</code> attribute is restored
(<code>spinner.setAttribute('hidden', '')</code>), hiding the spinner.
Ideally, this would happen after the data being fetched is returned.</p>
<p>Here&rsquo;s the <a href="https://codepen.io/wang0nya/pen/bzwQPr">pen</a></p>
]]></description></item><item><title>Skipping tests</title><link>https://wangonya.com/blog/pytest-skip/</link><pubDate>Thu, 31 Jan 2019 08:16:36 +0300</pubDate><guid>https://wangonya.com/blog/pytest-skip/</guid><description><![CDATA[<p>Sometimes you might want to skip a particular test while executing
others for some reason. Maybe the database guy isn&rsquo;t done setting up and that particular test requires a database connection. Instead of having to wait, you can just write the test and instruct pytest to skip it. Give the appropriate reason so it doesn&rsquo;t look like you just skipped a failing test to keep your test suite green.</p>
<p>There are a couple of ways to do this.</p>
<p>The simplest is to use the <code>@pytest.mark.skip</code> decorator like
so:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_stuff(): <span style="font-style:italic"># this test will be executed</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@pytest.mark.skip(reason=<span style="font-style:italic">&#34;just testing if skip works&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_other_stuff(): <span style="font-style:italic"># this one will be skipped</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span></code></pre></div><p>Running your tests should produce the output below:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 2 items
</span></span><span style="display:flex;"><span>skip.py .s                           [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>===================== 1 passed, 1 skipped in 0.05 seconds ===============
</span></span></code></pre></div><p>Notice the little <code>s</code>. It shows the test that was skipped.
Pytest also tells us that <code>1 passed, 1 skipped</code>. If you need
a more verbose output, you can use the <code>-rs</code> flag
<code>pytest skip.py -rs</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 2 items
</span></span><span style="display:flex;"><span>skip.py .s                    [100%]
</span></span><span style="display:flex;"><span>==================== short test summary info ===============
</span></span><span style="display:flex;"><span>SKIP [1] skip.py:14: just testing <span style="font-weight:bold">if</span> skip works
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>=================== 1 passed, 1 skipped in 0.02 seconds ==========
</span></span></code></pre></div><p>The test above was skipped even before it started. This isn&rsquo;t always
ideal. You can have more control over how the test is skipped by using
the <code>pytest.skip(reason)</code> function:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> setup_stuff():
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-weight:bold">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_stuff(): <span style="font-style:italic"># this test will be executed</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_other_stuff(): <span style="font-style:italic"># this one will be skipped if setup_stuff() returns false</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> setup_stuff():
</span></span><span style="display:flex;"><span>        pytest.skip(<span style="font-style:italic">&#34;setup failed&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">pass</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 2 items
</span></span><span style="display:flex;"><span>skip.py .s                  [100%]
</span></span><span style="display:flex;"><span>=================== short test summary info =============================
</span></span><span style="display:flex;"><span>SKIP [1] skip.py:12: setup failed
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>==================== 1 passed, 1 skipped in 0.05 seconds =================
</span></span></code></pre></div><p>If you prefer to check that the condition is satisfied before the test
starts, then you can use <code>skipif</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> setup_stuff():
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-weight:bold">False</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_stuff(): <span style="font-style:italic"># this test will be executed</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>@pytest.mark.skipif(<span style="font-weight:bold">not</span> setup_stuff(), reason=<span style="font-style:italic">&#34;setup failed&#34;</span>)
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_other_stuff(): <span style="font-style:italic"># this one will be skipped if setup_stuff() returns false</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 2 items
</span></span><span style="display:flex;"><span>skip.py .s                  [100%]
</span></span><span style="display:flex;"><span>=================== short test summary info =============================
</span></span><span style="display:flex;"><span>SKIP [1] skip.py:12: setup failed
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>==================== 1 passed, 1 skipped in 0.05 seconds =================
</span></span></code></pre></div><p>There are many other ways you can customize your tests to skip depending
on certain conditions as explained in the
<a href="https://docs.pytest.org/en/latest/skipping.html">docs</a>.</p>
]]></description></item><item><title>Capturing print statements while debugging</title><link>https://wangonya.com/blog/pytest-capture-print/</link><pubDate>Wed, 30 Jan 2019 08:06:29 +0300</pubDate><guid>https://wangonya.com/blog/pytest-capture-print/</guid><description><![CDATA[<p>You might need to capture print statements in your tests while
debugging. This might be just to help you debug, or for some other
reason. I mostly do this kind of thing when testing for database
connections where, in addition to other tests, I want to make sure I see
that &quot;Database connection successful&quot; message.</p>
<p>Let&rsquo;s demonstrate with a simple example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> add_numbers(num1, num2):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Add function started...&#34;</span>)
</span></span><span style="display:flex;"><span>    result = num1 + num2
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Numbers added. Returning result...&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> result
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_add_numbers():
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> add_numbers(2, 3) == 3
</span></span></code></pre></div><p>Running the test above fails with the given traceback:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>print.py F                 [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>============================ FAILURES ============================
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    def test_add_numbers():
</span></span><span style="display:flex;"><span>&gt;       assert add_numbers(2, 3) == 3
</span></span><span style="display:flex;"><span>E       assert 5 == 3
</span></span><span style="display:flex;"><span>E        +  where 5 = add_numbers(2, 3)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print.py:9: AssertionError
</span></span><span style="display:flex;"><span>---------------------- Captured stdout call ----------------------------
</span></span><span style="display:flex;"><span>Add <span style="font-weight:bold">function</span> started...
</span></span><span style="display:flex;"><span>Numbers added. Returning result...
</span></span><span style="display:flex;"><span>===================== 1 failed in 0.11 seconds ====================
</span></span></code></pre></div><p>Notice the <code>Captured stdout call</code> section. It captured out
two print statements. During test execution, any output sent to stdout
and stderr is captured. By default, the captured output is only
displayed if the test fails. Changing our
<code>assert add_numbers(2, 3) == 3</code> to
<code>assert add_numbers(2, 3) == 5</code> and running the test again
gives the following output:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>print.py .                       [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>========================= 1 passed in 0.05 seconds ===========================
</span></span></code></pre></div><p>You can access your captured output in your tests by using
<code>readouterr()</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> add_numbers(num1, num2):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Add function started...&#34;</span>)
</span></span><span style="display:flex;"><span>    result = num1 + num2
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Numbers added. Returning result...&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> result
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_add_numbers(capsys):
</span></span><span style="display:flex;"><span>    result = add_numbers(2, 3)
</span></span><span style="display:flex;"><span>    captured = capsys.readouterr()
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Hello&#34;</span> <span style="font-weight:bold">in</span> captured.out
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> result == 3
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>print.py F                             [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>====================== FAILURES =======================
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>capsys = &lt;_pytest.capture.CaptureFixture object at 0x10ba25d30&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    def test_add_numbers(capsys):
</span></span><span style="display:flex;"><span>        result = add_numbers(2, 3)
</span></span><span style="display:flex;"><span>        captured = capsys.readouterr()
</span></span><span style="display:flex;"><span>&gt;       assert <span style="font-style:italic">&#34;Hello&#34;</span> in captured.out
</span></span><span style="display:flex;"><span>E       AssertionError: assert <span style="font-style:italic">&#39;Hello&#39;</span> in <span style="font-style:italic">&#39;Add function started...\nNumbers added. Returning result...\n&#39;</span>
</span></span><span style="display:flex;"><span>E        +  where <span style="font-style:italic">&#39;Add function started...\nNumbers added. Returning result...\n&#39;</span> = CaptureResult(out=<span style="font-style:italic">&#39;Add function started...\nNumbers added. Returning result...\n&#39;</span>, err=<span style="font-style:italic">&#39;&#39;</span>).out
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print.py:11: AssertionError
</span></span><span style="display:flex;"><span>======================== 1 failed in 0.09 seconds =======================
</span></span></code></pre></div><p>It&rsquo;s important to note that each <code>readouterr()</code> call
snapshots the output so far, so we can call it repeatedly, checking the
output of our test step by step.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> add_numbers(num1, num2):
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Add function started...&#34;</span>)
</span></span><span style="display:flex;"><span>    result = num1 + num2
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;Numbers added. Returning result...&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> result
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_add_numbers(capsys):
</span></span><span style="display:flex;"><span>    result = add_numbers(2, 3)
</span></span><span style="display:flex;"><span>    captured = capsys.readouterr()
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Add function started&#34;</span> <span style="font-weight:bold">in</span> captured.out
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> <span style="font-style:italic">&#34;Numbers added. Returning result&#34;</span> <span style="font-weight:bold">in</span> captured.out
</span></span><span style="display:flex;"><span>    <span style="font-style:italic"># thus far, readouterr() out only has the two print statements from the add_numbers function</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> result == 5
</span></span><span style="display:flex;"><span>    print(<span style="font-style:italic">&#34;thank you, next&#34;</span>)
</span></span><span style="display:flex;"><span>    captured = capsys.readouterr()
</span></span><span style="display:flex;"><span>    <span style="font-style:italic"># here, readouterr() out doesn&#39;t have the two outputs from above</span>
</span></span><span style="display:flex;"><span>    <span style="font-style:italic"># it now contains the new value, &#34;thank you, next&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> captured.out == <span style="font-style:italic">&#34;thank you, next</span><span style="font-weight:bold;font-style:italic">\n</span><span style="font-style:italic">&#34;</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>print.py .                       [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>========================= 1 passed in 0.05 seconds ===========================
</span></span></code></pre></div>]]></description></item><item><title>Asserting exceptions with pytest</title><link>https://wangonya.com/blog/pytest-asserting-exceptions/</link><pubDate>Tue, 29 Jan 2019 05:15:40 +0300</pubDate><guid>https://wangonya.com/blog/pytest-asserting-exceptions/</guid><description><![CDATA[<p>The first time I had someone review my pull requests, she was pretty strict
on tests. I couldn&rsquo;t merge if the tests were failing, of course. But I
also couldn&rsquo;t merge if coverage had decreased. TDD was still new to me
so maintaining coverage was a challenge since I was only testing the
bare minimum I could. I had to find out how to make my tests more robust
and ensure as much of my code was tested as possible. One area that I
wasn&rsquo;t really sure how to test was the custom exceptions I had written.</p>
<p>Here&rsquo;s an example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># login.py</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> check_email_format(email):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;check that the entered email format is correct&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_email_exception():
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;test that exception is raised for invalid emails&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span></code></pre></div><p>This is probably something you want to do if you&rsquo;re implementing a
system with email authentication. The example is oversimplified, but it
serves the purpose of this post well.</p>
<p>To test for raised exceptions, pytest offers a handy method:
<code>pytest.raises</code>. Let&rsquo;s see how to use it in our example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">re</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> check_email_format(email):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;check that the entered email format is correct&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> re.<span style="font-weight:bold">match</span>(<span style="font-style:italic">r</span><span style="font-style:italic">&#34;(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)&#34;</span>, email):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">raise</span> <span style="font-weight:bold">Exception</span>(<span style="font-style:italic">&#34;Invalid email format&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> <span style="font-style:italic">&#34;Email format is ok&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_email_exception():
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;test that exception is raised for invalid emails&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">with</span> pytest.raises(<span style="font-weight:bold">Exception</span>):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">assert</span> check_email_format(<span style="font-style:italic">&#34;good@email.com&#34;</span>)
</span></span></code></pre></div><p>The <code>check_email_format</code> method takes in an email and checks
that it matches the regex pattern given. If it does, it returns
<code>&quot;Email format is ok&quot;</code>, otherwise, an exception is raised.</p>
<p>Using <code>pytest.raises</code> in a <code>with</code> block as a
context manager, we can check that an exception is actually raised if an
invalid email is given. Running the tests on the code as it is above
should fail:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>login.py F                [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>==================== FAILURES ========================
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    def test_email_exception():
</span></span><span style="display:flex;"><span>        <span style="font-style:italic">&#34;&#34;&#34;test that exception is raised for invalid emails&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>        with pytest.raises(Exception):
</span></span><span style="display:flex;"><span>&gt;           assert check_email_format(<span style="font-style:italic">&#34;good@email.com&#34;</span>)
</span></span><span style="display:flex;"><span>E           Failed: DID NOT RAISE &lt;class <span style="font-style:italic">&#39;Exception&#39;</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>login.py:16: Failed
</span></span></code></pre></div><p>Notice it says <code>Failed: DID NOT RAISE &lt;class 'Exception'&gt;</code>.
If an exception is not raised, the test fails. I found this particularly useful. We passed in a valid email format (according to our standards
here) so the test works as expected. Now we can make it pass.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">re</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> check_email_format(email):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;check that the entered email format is correct&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> re.<span style="font-weight:bold">match</span>(<span style="font-style:italic">r</span><span style="font-style:italic">&#34;(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)&#34;</span>, email):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">raise</span> <span style="font-weight:bold">Exception</span>(<span style="font-style:italic">&#34;Invalid email format&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> <span style="font-style:italic">&#34;Email format is ok&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_email_exception():
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;test that exception is raised for invalid emails&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">with</span> pytest.raises(<span style="font-weight:bold">Exception</span>):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">assert</span> check_email_format(<span style="font-style:italic">&#34;bademail.com&#34;</span>) <span style="font-style:italic"># invalid email format to raise exception</span>
</span></span></code></pre></div><p>Run your test: <code>pytest login.py</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>login.py .              [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>====================== 1 passed in 0.05 seconds ======================
</span></span></code></pre></div><p>You can also add an extra check for the exception message:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">re</span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">pytest</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> check_email_format(email):
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;check that the entered email format is correct&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> <span style="font-weight:bold">not</span> re.<span style="font-weight:bold">match</span>(<span style="font-style:italic">r</span><span style="font-style:italic">&#34;(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)&#34;</span>, email):
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">raise</span> <span style="font-weight:bold">Exception</span>(<span style="font-style:italic">&#34;Invalid email format&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">return</span> <span style="font-style:italic">&#34;Email format is ok&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_email_exception():
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">&#34;&#34;&#34;test that exception is raised for invalid emails&#34;&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">with</span> pytest.raises(<span style="font-weight:bold">Exception</span>) <span style="font-weight:bold">as</span> e:
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">assert</span> check_email_format(<span style="font-style:italic">&#34;bademail.com&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> str(e.value) == <span style="font-style:italic">&#34;Invalid email format&#34;</span>
</span></span></code></pre></div>]]></description></item><item><title>Getting started with pytest</title><link>https://wangonya.com/blog/getting-started-with-pytest/</link><pubDate>Mon, 28 Jan 2019 08:15:40 +0300</pubDate><guid>https://wangonya.com/blog/getting-started-with-pytest/</guid><description><![CDATA[<p>Test-Driven Development is great. If you&rsquo;re a Pythonista, it gets even
better with pytest - a framework that makes building simple and scalable
tests easy.</p>
<p>In this series, I&rsquo;ll be exploring the cool features that pytest offers
to help make testing Python code a breeze.</p>
<h2 id="preparing-your-python-environment">Preparing your python environment</h2>
<p>Let&rsquo;s set up our testing environment with <code>virtualenv</code>.
We&rsquo;ll be working with Python 3. <code>cd</code> into your working
directory and create a new virtual environment:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>python3 -m venv env
</span></span></code></pre></div><p>Activate the virtual environment:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>source env/bin/activate
</span></span></code></pre></div><h3 id="installing-pytest">Installing <code>pytest</code></h3>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>pip install pytest
</span></span></code></pre></div><p>That&rsquo;s all you need to do to get pytest ready. You can check the
installed version by running:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>pytest --version
</span></span></code></pre></div><h2 id="creating-your-first-test">Creating your first test</h2>
<p>Say we need to create an app that says hello to the name you give it
when it runs.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-style:italic"># simple hello world test</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello_world(name):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">pass</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_hello():
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> hello_world(<span style="font-style:italic">&#34;World!&#34;</span>) == <span style="font-style:italic">&#34;Hello World!&#34;</span>
</span></span></code></pre></div><p>You&rsquo;ll notice that our test function name begins with the word <em>test</em>.
That&rsquo;s how pytest discovers test methods. Also:</p>
<ul>
<li>Test files should be named <code>test_&lt;something&gt;.py</code> or
<code>&lt;something&gt;_test.py</code></li>
<li>Test classes should be named <code>Test&lt;Something&gt;</code></li>
</ul>
<p>Running <code>pytest hello.py</code> should return:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>hello.py F                         [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>===================== FAILURES ======================
</span></span><span style="display:flex;"><span>    def test_hello():
</span></span><span style="display:flex;"><span>&gt;       assert hello_world(<span style="font-style:italic">&#34;World!&#34;</span>) == <span style="font-style:italic">&#34;Hello World!&#34;</span>
</span></span><span style="display:flex;"><span>E       AssertionError: assert None == <span style="font-style:italic">&#39;Hello World!&#39;</span>
</span></span><span style="display:flex;"><span>E        +  where None = hello_world(<span style="font-style:italic">&#39;World!&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>hello.py:6: AssertionError
</span></span></code></pre></div><p>Pytest shows why the test failed:
<code>AssertionError: assert None == 'Hello World!'</code>. Obviously,
we have no code in our hello function so let&rsquo;s fix that.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">def</span> hello_world(name):
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-style:italic">&#34;Hello </span><span style="font-weight:bold;font-style:italic">{}</span><span style="font-style:italic">&#34;</span>.format(name)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">def</span> test_hello():
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">assert</span> hello_world(<span style="font-style:italic">&#34;World!&#34;</span>) == <span style="font-style:italic">&#34;Hello World!&#34;</span>
</span></span></code></pre></div><p>Running <code>pytest hello.py</code> should now return:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>collected 1 item
</span></span><span style="display:flex;"><span>hello.py .                       [100%]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>==================== 1 passed in 0.04 seconds ======================
</span></span></code></pre></div><p>As you can see, it&rsquo;s pretty easy to get started with testing in python
with pytest. Now that we have everything set up, we&rsquo;ll be going into
more advanced features as the series continues.</p>
]]></description></item><item><title>Python's heapq module</title><link>https://wangonya.com/blog/heapq/</link><pubDate>Fri, 21 Dec 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/heapq/</guid><description><![CDATA[<p>Often when working with collections of data, you may want to find the
smallest or largest item. It&rsquo;s easy enough to write a function that
iterates through the items and returns the smallest or largest one, or
use the builtin <code>min()</code>, <code>max()</code>, or
<code>sorted()</code> functions. Another interesting way may be
implementing a heap (priority) queue.</p>
<p>Python provides a pretty convenient module called <code>heapq</code>
that does that for you. <code>heapq</code> comes with a cool set of
inbuilt functions that you can read more about in the
<a href="https://docs.python.org/3.0/library/heapq.html">docs</a>.</p>
<h2 id="finding-the-smallest-items">Finding the smallest items</h2>
<p>Find 3 of the smallest items using the <code>nsmallest</code> function:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">heapq</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>numbers = [9, 45, 21, 4, 63, 3, 109]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(heapq.nsmallest(3, numbers)) <span style="font-style:italic"># [3, 4, 9]</span>
</span></span></code></pre></div><p>Also, converting a list into a heap using the <code>heapify</code>
function automatically sets the smallest item as the first:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">heapq</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>numbers = [9, 45, 21, 4, 63, 3, 109]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>heapq.heapify(numbers)
</span></span><span style="display:flex;"><span>print(numbers)
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output: [3, 4, 9, 45, 63, 21, 109]</span>
</span></span></code></pre></div><p>You can then pop from the heap with <code>heappop()</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span>heapq.heappop(numbers) <span style="font-style:italic"># 3</span>
</span></span><span style="display:flex;"><span>print(numbers)
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output: [4, 45, 9, 109, 63, 21]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>heapq.heappop(numbers) <span style="font-style:italic"># 4</span>
</span></span><span style="display:flex;"><span>print(numbers)
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output: [9, 45, 21, 109, 63]</span>
</span></span></code></pre></div><h2 id="finding-the-largest-items">Finding the largest items</h2>
<p>Find 3 of the largest items using the <code>nlargest</code> function:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">heapq</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>numbers = [9, 45, 21, 4, 63, 3, 109]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>print(heapq.nlargest(3, numbers)) <span style="font-style:italic"># [109, 63, 45]</span>
</span></span></code></pre></div><h2 id="a-more-practical-example">A more practical example</h2>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="font-weight:bold">import</span> <span style="font-weight:bold">heapq</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>people = [
</span></span><span style="display:flex;"><span>    {<span style="font-style:italic">&#39;fname&#39;</span>: <span style="font-style:italic">&#39;John&#39;</span>, <span style="font-style:italic">&#39;lname&#39;</span>: <span style="font-style:italic">&#39;Doe&#39;</span>, <span style="font-style:italic">&#39;age&#39;</span>: 30},
</span></span><span style="display:flex;"><span>    {<span style="font-style:italic">&#39;fname&#39;</span>: <span style="font-style:italic">&#39;Jane&#39;</span>, <span style="font-style:italic">&#39;lname&#39;</span>: <span style="font-style:italic">&#39;Doe&#39;</span>, <span style="font-style:italic">&#39;age&#39;</span>: 25},
</span></span><span style="display:flex;"><span>    {<span style="font-style:italic">&#39;fname&#39;</span>: <span style="font-style:italic">&#39;Janie&#39;</span>, <span style="font-style:italic">&#39;lname&#39;</span>: <span style="font-style:italic">&#39;Doe&#39;</span>, <span style="font-style:italic">&#39;age&#39;</span>: 10},
</span></span><span style="display:flex;"><span>    {<span style="font-style:italic">&#39;fname&#39;</span>: <span style="font-style:italic">&#39;Jane&#39;</span>, <span style="font-style:italic">&#39;lname&#39;</span>: <span style="font-style:italic">&#39;Roe&#39;</span>, <span style="font-style:italic">&#39;age&#39;</span>: 22},
</span></span><span style="display:flex;"><span>    {<span style="font-style:italic">&#39;fname&#39;</span>: <span style="font-style:italic">&#39;Johnny&#39;</span>, <span style="font-style:italic">&#39;lname&#39;</span>: <span style="font-style:italic">&#39;Doe&#39;</span>, <span style="font-style:italic">&#39;age&#39;</span>: 12},
</span></span><span style="display:flex;"><span>    {<span style="font-style:italic">&#39;fname&#39;</span>: <span style="font-style:italic">&#39;John&#39;</span>, <span style="font-style:italic">&#39;lname&#39;</span>: <span style="font-style:italic">&#39;Roe&#39;</span>, <span style="font-style:italic">&#39;age&#39;</span>: 45}
</span></span><span style="display:flex;"><span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>oldest = heapq.nlargest(2, people, key=<span style="font-weight:bold">lambda</span> s: s[<span style="font-style:italic">&#39;age&#39;</span>])
</span></span><span style="display:flex;"><span>print(oldest)
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output:</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># [{&#39;fname&#39;: &#39;John&#39;, &#39;lname&#39;: &#39;Roe&#39;, &#39;age&#39;: 45},</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># {&#39;fname&#39;: &#39;John&#39;, &#39;lname&#39;: &#39;Doe&#39;, &#39;age&#39;: 30}]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>youngest = heapq.nsmallest(2, people, key=<span style="font-weight:bold">lambda</span> s: s[<span style="font-style:italic">&#39;age&#39;</span>])
</span></span><span style="display:flex;"><span>print(youngest)
</span></span><span style="display:flex;"><span><span style="font-style:italic"># Output:</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># [{&#39;fname&#39;: &#39;Janie&#39;, &#39;lname&#39;: &#39;Doe&#39;, &#39;age&#39;: 10},</span>
</span></span><span style="display:flex;"><span><span style="font-style:italic"># {&#39;fname&#39;: &#39;Johnny&#39;, &#39;lname&#39;: &#39;Doe&#39;, &#39;age&#39;: 12}]</span>
</span></span></code></pre></div><p>It should be noted though that the <code>nsmallest(n, iterable)</code>
and <code>nlargest(n, iterable)</code> functions perform best for
smaller values of <code>n</code>. For larger values, it is more
efficient to use the <code>sorted()</code> function. Also, when
<code>n==1</code>, it is more efficient to use the builtin
<code>min()</code> and <code>max()</code> functions.</p>
]]></description></item><item><title>Sorting algorithms with Javascript (Part 2)</title><link>https://wangonya.com/blog/js-sort-2/</link><pubDate>Sun, 04 Nov 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/js-sort-2/</guid><description><![CDATA[<p>I&rsquo;m going to show Javascript implementations of three more sorting
algorithms:</p>
<ul>
<li>Quick sort</li>
<li>Heap sort</li>
<li>Counting sort</li>
</ul>
<p>Again, this is not intended to be an in-depth explanation on the ins and
outs of how the algorithms work and their performance. If you&rsquo;d rather
read about that, here&rsquo;s a nice resource I found: <a href="https://brilliant.org/wiki/sorting-algorithms/">Sorting
Algorithms</a></p>
<p>To keep things simple, I&rsquo;ll be sorting a simple list <code>list</code>
having only 5 elements <code>[4, 2, 3, 1, 5]</code>.</p>
<h2 id="quick-sort">Quick Sort</h2>
<p>Like merge sort, this algorithm takes a divide-and-conquer approach. It
works by picking a pivot and dividing the list in relation to that
pivot: all elements greater than the pivot go to the right of the pivot,
and all elements less than or equal to the pivot go to the left of the
pivot. Elements on both sides are quick sorted, and this is repeated
until the complete list is sorted.</p>
<p>Visual</p>
<p>The visual on this wasn&rsquo;t very clear in illustrating how the algorithm
actually works so <a href="https://www.youtube.com/watch?v=PgBzjlCcFvc">here&rsquo;s a
video</a> instead.</p>
<p>Code</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">function</span> quickSort(list) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">if</span> (list.length &lt;= 1) {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> list;
</span></span><span style="display:flex;"><span>  } <span style="font-weight:bold">else</span> {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> left = [];
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> right = [];
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> sorted = [];
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> pivot = list.pop(); <span style="font-style:italic">// we&#39;re picking the last item to act as the pivot
</span></span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> length = list.length;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">for</span> (<span style="font-weight:bold">let</span> i = 0; i &lt; length; i++) {
</span></span><span style="display:flex;"><span>      <span style="font-weight:bold">if</span> (list[i] &lt;= pivot) {
</span></span><span style="display:flex;"><span>        left.push(list[i]);
</span></span><span style="display:flex;"><span>      } <span style="font-weight:bold">else</span> {
</span></span><span style="display:flex;"><span>        right.push(list[i]);
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> sorted.concat(quickSort(left), pivot, quickSort(right));
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> list = [4, 2, 3, 1, 5];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> sorted = quickSort(list);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(sorted);
</span></span></code></pre></div><h2 id="heap-sort">Heap Sort</h2>
<p>This algorithm takes advantage of a data structure known as a
<a href="https://brilliant.org/wiki/binary-heap/">binary-heap</a>. Heap sort works
by creating a Max heap to sort the elements in ascending order, then
swapping the root node with the last node, and deleting the sorted node
from the heap every time this is done.</p>
<p>Visual</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/36sw7hiikhyv1mrwmz4g.gif" alt="heap-sort">
</p>
<p>Code</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// create max heap
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> maxHeap(input, i) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> left = 2 * i + 1;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> right = 2 * i + 2;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> max = i;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">if</span> (left &lt; arrLength &amp;&amp; input[left] &gt; input[max]) {
</span></span><span style="display:flex;"><span>    max = left;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">if</span> (right &lt; arrLength &amp;&amp; input[right] &gt; input[max]) {
</span></span><span style="display:flex;"><span>    max = right;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">if</span> (max != i) {
</span></span><span style="display:flex;"><span>    swap(input, i, max);
</span></span><span style="display:flex;"><span>    maxHeap(input, max);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> swap(input, indexA, indexB) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> temp = input[indexA];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  input[indexA] = input[indexB];
</span></span><span style="display:flex;"><span>  input[indexB] = temp;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> heapSort(input) {
</span></span><span style="display:flex;"><span>  arrLength = input.length;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">for</span> (<span style="font-weight:bold">let</span> i = Math.floor(arrLength / 2); i &gt;= 0; i -= 1) {
</span></span><span style="display:flex;"><span>    maxHeap(input, i);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">for</span> (i = input.length - 1; i &gt; 0; i--) {
</span></span><span style="display:flex;"><span>    swap(input, 0, i);
</span></span><span style="display:flex;"><span>    arrLength--;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    maxHeap(input, 0);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">let</span> arrLength;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> list = [4, 2, 3, 1, 5];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> sorted = heapSort(list);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(list);
</span></span></code></pre></div><h2 id="counting-sort">Counting Sort</h2>
<p>You&rsquo;ll find counting sort to be rather unique compared to the
algorithms we&rsquo;ve covered so far. This is because it does not compare
elements while sorting. It works based on numeric keys. It does this by
creating a counting array, then using it to determine an element&rsquo;s
correct position.</p>
<p>Visual</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/w4jk13diiokecdhny33z.gif" alt="counting-sort">
</p>
<p>Code</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">function</span> countingSort(list, min, max) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> i;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> z = 0;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> count = [];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">for</span> (i = min; i &lt;= max; i++) {
</span></span><span style="display:flex;"><span>    count[i] = 0;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">for</span> (i = 0; i &lt; list.length; i++) {
</span></span><span style="display:flex;"><span>    count[list[i]]++;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">for</span> (i = min; i &lt;= max; i++) {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">while</span> (count[i]-- &gt; 0) {
</span></span><span style="display:flex;"><span>      list[z++] = i;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span> list;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> list = [4, 2, 3, 1, 5];
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> min = Math.min(...list);
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> max = Math.max(...list);
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> sorted = countingSort(list, min, max);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(sorted);
</span></span></code></pre></div>]]></description></item><item><title>Sorting algorithms with Javascript (Part 1)</title><link>https://wangonya.com/blog/js-sort-1/</link><pubDate>Thu, 18 Oct 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/js-sort-1/</guid><description><![CDATA[<p>I&rsquo;ve been learning a lot about data structures and algorithms lately
and I&rsquo;ve noticed in my reading that there aren&rsquo;t a lot of examples
showing implementations of algorithms in Javascript. You&rsquo;ll mostly find
examples in Java, Python, C, C++ etc. Maybe there&rsquo;s a reason for
preferring these languages over Javascript? I&rsquo;m not sure.</p>
<p>In this first part, I&rsquo;m going to show Javascript implementations of
three sorting algorithms:</p>
<ul>
<li>Merge sort</li>
<li>Insertion sort</li>
<li>Bubble sort</li>
</ul>
<p>This is not intended to be an in-depth explanation on the ins and outs
of how the algorithms work and their performance. If you&rsquo;d rather read
about that, here&rsquo;s a nice resource I found: <a href="https://brilliant.org/wiki/sorting-algorithms/">Sorting
Algorithms</a></p>
<p>To keep things simple, I&rsquo;ll be sorting a simple list <code>list</code>
having only 5 elements <code>[4, 2, 3, 1, 5]</code>.</p>
<h2 id="merge-sort">Merge Sort</h2>
<p>Merge sort uses a divide-and-conquer approach to sort elements in an
array. Basically, what this means is that instead of dealing with the
array as a whole, it continually splits it in half until both halves are
sorted, then the halves are merged into one solved list.</p>
<p>Visual</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/1npt37z4g0zjxiicljlm.gif" alt="merge-sort">
</p>
<p>Code</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">function</span> mergeSort(list) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> len = list.length;
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">// an array of length == 1 is technically a sorted list
</span></span></span><span style="display:flex;"><span>  <span style="font-weight:bold">if</span> (len == 1) {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> list;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">// get mid item
</span></span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> middleIndex = Math.ceil(len / 2);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">// split current list into two: left and right list
</span></span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> leftList = list.slice(0, middleIndex);
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> rightList = list.slice(middleIndex, len);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  leftList = mergeSort(leftList);
</span></span><span style="display:flex;"><span>  rightList = mergeSort(rightList);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span> merge(leftList, rightList);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">// Solve the sub-problems and merge them together
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> merge(leftList, rightList) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> sorted = [];
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">while</span> (leftList.length &gt; 0 &amp;&amp; rightList.length &gt; 0) {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> leftItem = leftList[0];
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">const</span> rightItem = rightList[0];
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> (leftItem &gt; rightItem) {
</span></span><span style="display:flex;"><span>      sorted.push(rightItem);
</span></span><span style="display:flex;"><span>      rightList.shift();
</span></span><span style="display:flex;"><span>    } <span style="font-weight:bold">else</span> {
</span></span><span style="display:flex;"><span>      sorted.push(leftItem);
</span></span><span style="display:flex;"><span>      leftList.shift();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">// if left list has items, add what is left to the results
</span></span></span><span style="display:flex;"><span>  <span style="font-weight:bold">while</span> (leftList.length !== 0) {
</span></span><span style="display:flex;"><span>    sorted.push(leftList[0]);
</span></span><span style="display:flex;"><span>    leftList.shift();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">// if right list has items, add what is left to the results
</span></span></span><span style="display:flex;"><span>  <span style="font-weight:bold">while</span> (rightList.length !== 0) {
</span></span><span style="display:flex;"><span>    sorted.push(rightList[0]);
</span></span><span style="display:flex;"><span>    rightList.shift();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">// merge the left and right list
</span></span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span> sorted;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> list = [4, 2, 3, 1, 5];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> sorted = mergeSort(list);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(sorted);
</span></span></code></pre></div><h2 id="insertion-sort">Insertion Sort</h2>
<p>Insertion sort builds the final sorted list one element at a time. It
does this by taking one element, comparing it to the rest of the elements in
the list, finding its right position, and then placing it there.</p>
<p>This is known as comparison-based sorting.</p>
<p>Visual</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/g01s69r1ppo9kifien2v.gif" alt="insertion-sort">
</p>
<p>Code</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">function</span> insertionSort(list) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> len = list.length;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">for</span> (<span style="font-weight:bold">let</span> i = 1; i &lt; len; i++) {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">if</span> (list[i] &lt; list[0]) {
</span></span><span style="display:flex;"><span>      <span style="font-style:italic">// move current element to the first position
</span></span></span><span style="display:flex;"><span>      list.unshift(list.splice(i, 1)[0]);
</span></span><span style="display:flex;"><span>    } <span style="font-weight:bold">else</span> <span style="font-weight:bold">if</span> (list[i] &gt; list[i - 1]) {
</span></span><span style="display:flex;"><span>      <span style="font-style:italic">// maintain element position
</span></span></span><span style="display:flex;"><span>      <span style="font-weight:bold">continue</span>;
</span></span><span style="display:flex;"><span>    } <span style="font-weight:bold">else</span> {
</span></span><span style="display:flex;"><span>      <span style="font-style:italic">// find where element should go
</span></span></span><span style="display:flex;"><span>      <span style="font-weight:bold">for</span> (<span style="font-weight:bold">let</span> j = 1; j &lt; i; j++) {
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">if</span> (list[i] &gt; list[j - 1] &amp;&amp; list[i] &lt; list[j]) {
</span></span><span style="display:flex;"><span>          <span style="font-style:italic">// move element
</span></span></span><span style="display:flex;"><span>          list.splice(j, 0, list.splice(i, 1)[0]);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span> list;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> list = [4, 2, 3, 1, 5];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> sorted = insertionSort(list);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(sorted);
</span></span></code></pre></div><h2 id="bubble-sort">Bubble Sort</h2>
<p>Another example of a comparison-based sorting algorithm, Bubble sort
compares <em>each pair</em> of elements in a list and swaps them if they are
out of order until the list is sorted.</p>
<p>Visual</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/m4zwhvxf6ujdrvt9xoq5.gif" alt="bubble-sort">
</p>
<p>Code</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">function</span> bubbleSort(list) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> swapped;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">let</span> n = list.length - 1;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">do</span> {
</span></span><span style="display:flex;"><span>    swapped = <span style="font-weight:bold">false</span>;
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">for</span> (<span style="font-weight:bold">let</span> i = 0; i &lt; n; i++) {
</span></span><span style="display:flex;"><span>      <span style="font-style:italic">// compare pairs of elements
</span></span></span><span style="display:flex;"><span>      <span style="font-style:italic">// if left element &gt; right element, swap
</span></span></span><span style="display:flex;"><span>      <span style="font-weight:bold">if</span> (list[i] &gt; list[i + 1]) {
</span></span><span style="display:flex;"><span>        <span style="font-weight:bold">const</span> temp = list[i];
</span></span><span style="display:flex;"><span>        list[i] = list[i + 1];
</span></span><span style="display:flex;"><span>        list[i + 1] = temp;
</span></span><span style="display:flex;"><span>        swapped = <span style="font-weight:bold">true</span>;
</span></span><span style="display:flex;"><span>      }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  } <span style="font-weight:bold">while</span> (
</span></span><span style="display:flex;"><span>    <span style="font-style:italic">// continue swapping until sorted
</span></span></span><span style="display:flex;"><span>    swapped
</span></span><span style="display:flex;"><span>  );
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span> list;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> list = [4, 2, 3, 1, 5];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> sorted = bubbleSort(list);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(sorted);
</span></span></code></pre></div><p>That&rsquo;s it! And, in case you&rsquo;re wondering, I used
<a href="https://visualgo.net/en/sorting">this</a> site to make the visuals.</p>
<p>In the next part, I&rsquo;ll be going through:</p>
<ul>
<li>Quick sort</li>
<li>Heap sort</li>
<li>Counting sort</li>
</ul>
]]></description></item><item><title>Javascript lookaheads and lookbehinds</title><link>https://wangonya.com/blog/lookaheads-lookbehinds/</link><pubDate>Wed, 29 Aug 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/lookaheads-lookbehinds/</guid><description><![CDATA[<p>Regular expressions are patterns used to match character combinations in
strings. They help us work with strings in a very performant way.</p>
<p>By formulating regex with a special syntax, you can:</p>
<ul>
<li>search text in a string</li>
<li>replace substrings in a string</li>
<li>extract information from a string</li>
</ul>
<p>If all this is completely new to you, take a look at the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">mdn web
docs</a>
for more info.</p>
<p>For this post, I&rsquo;ll focus on one of the easier (and very useful) ways
you can use regex.</p>
<h2 id="lookaheads-match-a-string-depending-on-what-follows-it">Lookaheads: match a string depending on what follows it</h2>
<h3 id="format-xy">Format: <code>x(?=y)</code></h3>
<p><code>x(?=y)</code> matches &lsquo;x&rsquo; only if &lsquo;x&rsquo; is followed by &lsquo;y&rsquo;.
Let&rsquo;s see an example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// check to see if we have the right &#39;Kanye&#39;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">// /Kanye(?= West)/ : the string &#39;Kanye&#39; must be followed by &#39;West&#39;
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">/Kanye(?= West)/</span>.test(<span style="font-style:italic">&#39;I heard Kanye will be performing tonight&#39;</span>) <span style="font-style:italic">// false. we can&#39;t really be sure it&#39;s the right Kanye
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/Kanye(?= West)/</span>.test(<span style="font-style:italic">&#39;I heard Kanye East will be performing tonight&#39;</span>) <span style="font-style:italic">// false. Kanye who???
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/Kanye(?= West)/</span>.test(<span style="font-style:italic">&#39;I heard Kanye West will be performing tonight&#39;</span>) <span style="font-style:italic">// true
</span></span></span></code></pre></div><p>You can also do <code>/Kanye(?= West|East)/</code> to match Kanye if
it&rsquo;s followed by either &lsquo;East&rsquo; or &lsquo;West&rsquo;.</p>
<h3 id="format-xy-1">Format: <code>x(?!y)</code></h3>
<p><code>x(?!y)</code> performs the inverse operation, matching &lsquo;x&rsquo; only
if &lsquo;x&rsquo; is <strong>not</strong> followed by &lsquo;y&rsquo;. This is called a negated
lookahead.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// we want a different &#39;Kanye&#39;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">// /Kanye(?! West)/ : the string &#39;Kanye&#39; must not be followed by &#39;West&#39;
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">/Kanye(?! West)/</span>.test(<span style="font-style:italic">&#39;I heard Kanye will be performing tonight&#39;</span>) <span style="font-style:italic">// true. might be West, but I&#39;ll just take the risk and see
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/Kanye(?! West)/</span>.test(<span style="font-style:italic">&#39;I heard Kanye East will be performing tonight&#39;</span>) <span style="font-style:italic">// true. let&#39;s give the new guy a chance
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/Kanye(?! West)/</span>.test(<span style="font-style:italic">&#39;I heard Kanye West will be performing tonight&#39;</span>) <span style="font-style:italic">// false
</span></span></span></code></pre></div><h2 id="lookbehinds-match-a-string-depending-on-what-precedes-it">Lookbehinds: match a string depending on what precedes it</h2>
<p><strong>This is an
<a href="https://github.com/tc39/proposal-regexp-lookbehind">ES2018</a> feature</strong>
🎉🎊🚀🎸🤘🏾</p>
<h3 id="format-yx">Format: <code>(?&lt;=y)x</code></h3>
<p><code>(?&lt;=y)x</code> matches &lsquo;x&rsquo; only if it&rsquo;s preceded by &lsquo;y&rsquo;</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// check to see if we have the right &#39;Kanye West&#39;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">// /(?&lt;= Kanye) West/ : the string &#39;West&#39; must be preceded by &#39;Kanye&#39;
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">/(?&lt;= Kanye) West/</span>.test(<span style="font-style:italic">&#39;I heard West will be performing tonight&#39;</span>) <span style="font-style:italic">// false. we can&#39;t really be sure it&#39;s the right West
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/(?&lt;= Kanye) West/</span>.test(<span style="font-style:italic">&#39;I heard Keith West will be performing tonight&#39;</span>) <span style="font-style:italic">// false
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/(?&lt;= Kanye) West/</span>.test(<span style="font-style:italic">&#39;I heard Kanye West will be performing tonight&#39;</span>) <span style="font-style:italic">// true
</span></span></span></code></pre></div><h3 id="format-yx-1">Format: <code>(?&lt;!y)x</code></h3>
<p><code>(?&lt;!y)x</code> matches &lsquo;x&rsquo; only if it&rsquo;s <strong>not</strong> preceded by
&lsquo;y&rsquo;</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// check to see if we have another &#39;West&#39;
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">// /(?&lt;= Kanye) West/ : the string &#39;West&#39; must be not be preceded by &#39;Kanye&#39;
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-style:italic">/(?&lt;! Kanye) West/</span>.test(<span style="font-style:italic">&#39;I heard West will be performing tonight&#39;</span>) <span style="font-style:italic">// true
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/(?&lt;! Kanye) West/</span>.test(<span style="font-style:italic">&#39;I heard Keith West will be performing tonight&#39;</span>) <span style="font-style:italic">// true
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">/(?&lt;! Kanye) West/</span>.test(<span style="font-style:italic">&#39;I heard Kanye West will be performing tonight&#39;</span>) <span style="font-style:italic">// false
</span></span></span></code></pre></div><p>Regex might be a bit hard to master, but once you do, you&rsquo;ll find that
it makes working with strings so much easier.</p>
]]></description></item><item><title>Javascript array iteration with some() and every()</title><link>https://wangonya.com/blog/array-iteration/</link><pubDate>Tue, 28 Aug 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/array-iteration/</guid><description><![CDATA[<p>If you&rsquo;re using an array in your code, chances are, you&rsquo;ll need to
iterate over the values in the array. There&rsquo;s a couple of ways you can
do that, some better and more efficient than others depending on what
you want to accomplish.</p>
<p>For this post, I&rsquo;ll focus on two ways: <code>some()</code> and
<code>every()</code>.</p>
<h2 id="some"><code>some()</code></h2>
<p>The <code>some()</code> method tests whether <strong>at least one</strong> element in
the array passes the test implemented by the provided function. It
checks the elements one by one, and if it finds an array element where
the function returns a truthy value, <code>some()</code> returns
<code>true</code> and does not check the remaining values. Otherwise, it
returns <code>false</code>.</p>
<p>Let&rsquo;s say you want to check if a contact exists in your contact list:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> contacts = [<span style="font-style:italic">&#34;Stewie&#34;</span>, <span style="font-style:italic">&#34;Meg&#34;</span>, <span style="font-style:italic">&#34;Quagmire&#34;</span>, <span style="font-style:italic">&#34;Cleveland&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="font-weight:bold">function</span> checkContacts(arr, val) {
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">return</span> arr.some((arrVal) =&gt; val === arrVal);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>checkContacts(contacts, <span style="font-style:italic">&#34;Lois&#34;</span>); <span style="font-style:italic">// false
</span></span></span><span style="display:flex;"><span>checkContacts(contacts, <span style="font-style:italic">&#34;Meg&#34;</span>); <span style="font-style:italic">// true
</span></span></span></code></pre></div><p>When checking for <code>Lois</code>, <code>some()</code> checks the
array elements beginning at <code>Stewie</code> to the end, and having
not found a match, returns <code>false</code>. When checking for
<code>Meg</code>, it stops at <code>Meg</code> and returns
<code>true</code>, ignoring the rest of the elements.</p>
<h2 id="every"><code>every()</code></h2>
<p>This method tests whether <strong>all</strong> elements in the array pass the test
implemented by the provided function. It checks the elements one by one,
and if it finds an array element where the function returns a falsy
value, <code>every()</code> returns <code>false</code> and does not
check the remaining values. Otherwise, it returns <code>true</code>.</p>
<p>Let&rsquo;s check if all the names in our contacts list have more than 3
characters:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>[<span style="font-style:italic">&#34;Stewie&#34;</span>, <span style="font-style:italic">&#34;Meg&#34;</span>, <span style="font-style:italic">&#34;Quagmire&#34;</span>, <span style="font-style:italic">&#34;Cleveland&#34;</span>].every(
</span></span><span style="display:flex;"><span>  (contact) =&gt; contact.length &gt;= 4,
</span></span><span style="display:flex;"><span>); <span style="font-style:italic">// false
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="font-style:italic">&#34;Stewie&#34;</span>, <span style="font-style:italic">&#34;Megan&#34;</span>, <span style="font-style:italic">&#34;Quagmire&#34;</span>, <span style="font-style:italic">&#34;Cleveland&#34;</span>].every(
</span></span><span style="display:flex;"><span>  (contact) =&gt; contact.length &gt;= 4,
</span></span><span style="display:flex;"><span>); <span style="font-style:italic">// true
</span></span></span></code></pre></div><p>The first test returns <code>false</code> since <code>Meg</code> has
only 3 characters. Remember: for <code>every()</code>, <em>all</em> the
elements in the array have to be truthy for it to return
<code>true</code>. Changing <code>Meg</code> to <code>Megan</code> in
the second test therefore returns <code>true</code>.</p>
<p>These two methods can come in handy if you need to perform somewhat
similar tasks as described above. But of course, they&rsquo;re not the only
way.</p>
]]></description></item><item><title>'this' and arrow functions</title><link>https://wangonya.com/blog/arrow-this/</link><pubDate>Mon, 27 Aug 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/arrow-this/</guid><description><![CDATA[<p>Arrow functions were introduced in ES6 as a new syntax for writing
Javascript functions. Thanks to their short syntax, they encourage the
use of small functions, which make code look cleaner (and
<code>() =&gt;</code> just looks cooler 😄).</p>
<p>As a beginner just getting to wrap my head around ES6 syntax, I began
using arrow functions <strong>everywhere</strong> without really understanding how
they worked. As you might expect, I ended up running into some problems,
especially with the <code>this</code> keyword.</p>
<p><code>this</code> can get a bit confusing sometimes as its value varies
depending on the function&rsquo;s execution context, and on the mode (strict
or non-strict). Much has been written about the ins and outs of that so
I&rsquo;ll just focus on one thing:</p>
<h2 id="how-this-works-in-arrow-functions">How <code>this</code> works in arrow functions</h2>
<p>In a regular function, <code>this</code> refers to the object when
defined as a method of an object. We can therefore do:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> brunch = {
</span></span><span style="display:flex;"><span>  food: <span style="font-style:italic">&#34;Dim sum&#34;</span>,
</span></span><span style="display:flex;"><span>  beverage: <span style="font-style:italic">&#34;Jasmine tea&#34;</span>,
</span></span><span style="display:flex;"><span>  order: <span style="font-weight:bold">function</span> () {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-style:italic">`I&#39;ll have the </span><span style="font-weight:bold;font-style:italic">${</span><span style="font-weight:bold">this</span>.food<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic"> with </span><span style="font-weight:bold;font-style:italic">${</span><span style="font-weight:bold">this</span>.beverage<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic"> please.`</span>;
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Calling <code>brunch.order()</code> will return
<code>&quot;I'll have the Dim sum with Jasmine tea please.&quot;</code></p>
<p>Let&rsquo;s edit that and use an arrow function for <code>order:</code>:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> brunch = {
</span></span><span style="display:flex;"><span>  food: <span style="font-style:italic">&#34;Dim sum&#34;</span>,
</span></span><span style="display:flex;"><span>  beverage: <span style="font-style:italic">&#34;Jasmine tea&#34;</span>,
</span></span><span style="display:flex;"><span>  order: () =&gt; {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">return</span> <span style="font-style:italic">`I&#39;ll have the </span><span style="font-weight:bold;font-style:italic">${</span><span style="font-weight:bold">this</span>.food<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic"> with </span><span style="font-weight:bold;font-style:italic">${</span><span style="font-weight:bold">this</span>.beverage<span style="font-weight:bold;font-style:italic">}</span><span style="font-style:italic"> please.`</span>;
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>This time, calling <code>brunch.order()</code> returns
<code>&quot;I'll have the undefined with undefined please.&quot;</code> Both
<code>this.food</code> and <code>this.beverage</code> return
<code>undefined</code>.</p>
<p>It worked with the normal function, so what&rsquo;s going on? In the normal
function, <code>this</code> was our <code>order</code> object. When
using an arrow function, <code>this</code> is not bound to anything and
it just inherits from the parent scope which in this case is the window.
Adding a <code>console.log(this)</code> before the <code>return</code>
in the arrow function returns a <code>Window</code> object, so it&rsquo;s
looking for <code>Window.food</code> and <code>Window.beverage</code>
which will obviously both be <code>undefined</code>.</p>
<p>Arrow functions are therefore not suited as object methods.</p>
<p>Another common problem area would be with event handlers. Here&rsquo;s an
example:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="font-style:italic">&lt;!-- change button colour on click --&gt;</span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">style</span>&gt;
</span></span><span style="display:flex;"><span>  .<span style="font-weight:bold">on</span> {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">background</span>: <span style="font-weight:bold">red</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>&lt;/<span style="font-weight:bold">style</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">button</span> id=<span style="font-style:italic">&#34;click&#34;</span>&gt;Toggle&lt;/<span style="font-weight:bold">button</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">script</span>&gt;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> button = document.querySelector(<span style="font-style:italic">&#34;#click&#34;</span>);
</span></span><span style="display:flex;"><span>  button.addEventListener(<span style="font-style:italic">&#34;click&#34;</span>, <span style="font-weight:bold">function</span> () {
</span></span><span style="display:flex;"><span>    console.log(<span style="font-weight:bold">this</span>); <span style="font-style:italic">// button
</span></span></span><span style="display:flex;"><span>    <span style="font-weight:bold">this</span>.classList.toggle(<span style="font-style:italic">&#34;on&#34;</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>&lt;/<span style="font-weight:bold">script</span>&gt;
</span></span></code></pre></div><p>In the code above, <code>this</code> refers to the button. Clicking on
the button toggles the colour as expected. Change the function to an
arrow function:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span><span style="font-style:italic">&lt;!-- change button colour on click --&gt;</span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">style</span>&gt;
</span></span><span style="display:flex;"><span>  .<span style="font-weight:bold">on</span> {
</span></span><span style="display:flex;"><span>    <span style="font-weight:bold">background</span>: <span style="font-weight:bold">red</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>&lt;/<span style="font-weight:bold">style</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">button</span> id=<span style="font-style:italic">&#34;click&#34;</span>&gt;Toggle&lt;/<span style="font-weight:bold">button</span>&gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>&lt;<span style="font-weight:bold">script</span>&gt;
</span></span><span style="display:flex;"><span>  <span style="font-weight:bold">const</span> button = document.querySelector(<span style="font-style:italic">&#34;#click&#34;</span>);
</span></span><span style="display:flex;"><span>  button.addEventListener(<span style="font-style:italic">&#34;click&#34;</span>, () =&gt; {
</span></span><span style="display:flex;"><span>    console.log(<span style="font-weight:bold">this</span>); <span style="font-style:italic">// Window { ... }
</span></span></span><span style="display:flex;"><span>    <span style="font-weight:bold">this</span>.classList.toggle(<span style="font-style:italic">&#34;on&#34;</span>);
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>&lt;/<span style="font-weight:bold">script</span>&gt;
</span></span></code></pre></div><p>and <code>this</code> becomes the browser&rsquo;s <code>window</code>
attribute. Clicking the button will give a <code>TypeError</code> error.
If you rely on <code>this</code> in an event handler, a regular function
may be necessary.</p>
<p>So, as cool and popular as arrow functions may be, it&rsquo;s best to
understand how they work, and to know when to and not to use them.</p>
]]></description></item><item><title>Finding an element in the array (the ES5, ES6 and ES7 way)</title><link>https://wangonya.com/blog/finding-array/</link><pubDate>Sun, 26 Aug 2018 00:00:00 +0000</pubDate><guid>https://wangonya.com/blog/finding-array/</guid><description><![CDATA[<p>This&rsquo;ll be a quick one.</p>
<p>Say you want to check if a specific element exists in an array. There&rsquo;s
a couple of ways to do that:</p>
<h2 id="es5">ES5</h2>
<h3 id="indexof"><code>indexOf()</code></h3>
<p><code>indexOf</code> returns the index of the first matching item found,
or <code>-1</code> if not found.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// check if a Fortnite ninja exists in the array
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> ninjas = [<span style="font-style:italic">&#34;Alchemist&#34;</span>, <span style="font-style:italic">&#34;Brawler&#34;</span>, <span style="font-style:italic">&#34;Skirmisher&#34;</span>, <span style="font-style:italic">&#34;Harvester&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(ninjas.indexOf(<span style="font-style:italic">&#34;Brawler&#34;</span>)); <span style="font-style:italic">// 1
</span></span></span><span style="display:flex;"><span>console.log(ninjas.indexOf(<span style="font-style:italic">&#34;Harvester&#34;</span>)); <span style="font-style:italic">// 3
</span></span></span><span style="display:flex;"><span>console.log(ninjas.indexOf(<span style="font-style:italic">&#34;Assassin&#34;</span>)); <span style="font-style:italic">// -1 (doesn&#39;t exist)
</span></span></span></code></pre></div><h3 id="lastindexof"><code>lastIndexOf()</code></h3>
<p><code>lastIndexOf()</code> returns the index of the last matching item
found, or <code>-1</code> if not found.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-style:italic">// check if a Fortnite ninja exists in the array
</span></span></span><span style="display:flex;"><span><span style="font-style:italic">// note that &#39;Brawler&#39; exists twice
</span></span></span><span style="display:flex;"><span><span style="font-weight:bold">const</span> ninjas = [
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#34;Alchemist&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#34;Brawler&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#34;Skirmisher&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#34;Harvester&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#34;Brawler&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="font-style:italic">&#34;Stonefoot&#34;</span>,
</span></span><span style="display:flex;"><span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(ninjas.lastIndexOf(<span style="font-style:italic">&#34;Brawler&#34;</span>)); <span style="font-style:italic">// 4 (last one returned)
</span></span></span><span style="display:flex;"><span>console.log(ninjas.lastIndexOf(<span style="font-style:italic">&#34;Harvester&#34;</span>)); <span style="font-style:italic">// 3
</span></span></span><span style="display:flex;"><span>console.log(ninjas.lastIndexOf(<span style="font-style:italic">&#34;Assassin&#34;</span>)); <span style="font-style:italic">// -1 (doesn&#39;t exist)
</span></span></span></code></pre></div><h2 id="es6">ES6</h2>
<h3 id="find"><code>find()</code></h3>
<p>The <code>find()</code> method returns the <strong>value</strong> of the <strong>first</strong>
element in the array that satisfies the provided testing function.
Otherwise, undefined is returned.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> ninjas = [
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Alchemist&#34;</span> },
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Brawler&#34;</span> },
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Skirmisher&#34;</span> },
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Harvester&#34;</span> },
</span></span><span style="display:flex;"><span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(ninjas.find((ninja) =&gt; ninja.name === <span style="font-style:italic">&#34;Harvester&#34;</span>)); <span style="font-style:italic">// {name: &#34;Harvester&#34;}
</span></span></span><span style="display:flex;"><span>console.log(ninjas.find((ninja) =&gt; ninja.name === <span style="font-style:italic">&#34;Assassin&#34;</span>)); <span style="font-style:italic">// undefined
</span></span></span></code></pre></div><h3 id="findindex"><code>findIndex()</code></h3>
<p>Returns the <strong>index</strong> of the <strong>first</strong> element in the array that
satisfies the provided testing function. Otherwise, -1 is returned.</p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> ninjas = [
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Alchemist&#34;</span> },
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Brawler&#34;</span> },
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Skirmisher&#34;</span> },
</span></span><span style="display:flex;"><span>  { name: <span style="font-style:italic">&#34;Harvester&#34;</span> },
</span></span><span style="display:flex;"><span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(ninjas.findIndex((ninja) =&gt; ninja.name === <span style="font-style:italic">&#34;Harvester&#34;</span>)); <span style="font-style:italic">// 3
</span></span></span><span style="display:flex;"><span>console.log(ninjas.findIndex((ninja) =&gt; ninja.name === <span style="font-style:italic">&#34;Assassin&#34;</span>)); <span style="font-style:italic">// -1
</span></span></span></code></pre></div><h2 id="es7">ES7</h2>
<h3 id="includes"><code>includes()</code></h3>
<p>The <code>includes()</code> method determines whether an array includes
a certain element, returning true or false as appropriate. For example,
<code>a.includes(value)</code> returns <code>true</code> if
<code>a</code> contains <code>value</code></p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> ninjas = [<span style="font-style:italic">&#34;Alchemist&#34;</span>, <span style="font-style:italic">&#34;Brawler&#34;</span>, <span style="font-style:italic">&#34;Skirmisher&#34;</span>, <span style="font-style:italic">&#34;Harvester&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(ninjas.includes(<span style="font-style:italic">&#34;Brawler&#34;</span>)); <span style="font-style:italic">// true
</span></span></span><span style="display:flex;"><span>console.log(ninjas.includes(<span style="font-style:italic">&#34;Assassin&#34;</span>)); <span style="font-style:italic">// false
</span></span></span></code></pre></div><p><code>a.includes(value, i)</code> returns true if <code>a</code>
contains <code>value</code> <strong>after (or at) the position
<code>i</code></strong></p>
<div class="highlight"><pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="font-weight:bold">const</span> ninjas = [<span style="font-style:italic">&#34;Alchemist&#34;</span>, <span style="font-style:italic">&#34;Brawler&#34;</span>, <span style="font-style:italic">&#34;Skirmisher&#34;</span>, <span style="font-style:italic">&#34;Harvester&#34;</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>console.log(ninjas.includes(<span style="font-style:italic">&#34;Skirmisher&#34;</span>, 1)); <span style="font-style:italic">// true
</span></span></span><span style="display:flex;"><span>console.log(ninjas.includes(<span style="font-style:italic">&#34;Skirmisher&#34;</span>, 2)); <span style="font-style:italic">// true
</span></span></span><span style="display:flex;"><span>console.log(ninjas.includes(<span style="font-style:italic">&#34;Skirmisher&#34;</span>, 3)); <span style="font-style:italic">// false
</span></span></span></code></pre></div>]]></description></item></channel></rss>